Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Leherbauer2012-01-23 09:28:01 +0000
committerAnton Leherbauer2012-01-23 09:28:01 +0000
commit6f047bf6a21dcc9be9bf444da123e8b32834da52 (patch)
tree22cc2972f8bfa7a3693aa514ecef25581dd2dd32
parenta1b540e1272eda3d1b09f3232512db9cc0f1d168 (diff)
downloadorg.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.tar.gz
org.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.tar.xz
org.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.zip
TCF Python: Unify line endings.
-rw-r--r--python/.project34
-rw-r--r--python/src/tcf/EventQueue.py162
-rw-r--r--python/src/tcf/__init__.py126
-rw-r--r--python/src/tcf/channel/ChannelProxy.py194
-rw-r--r--python/src/tcf/channel/StreamChannel.py260
-rw-r--r--python/src/tcf/channel/__init__.py378
-rw-r--r--python/src/tcf/errors.py322
-rw-r--r--python/src/tcf/peer.py548
-rw-r--r--python/src/tcf/services/__init__.py254
-rw-r--r--python/src/tcf/services/breakpoints.py626
-rw-r--r--python/src/tcf/services/diagnostics.py570
-rw-r--r--python/src/tcf/services/disassembly.py262
-rw-r--r--python/src/tcf/services/expressions.py712
-rw-r--r--python/src/tcf/services/filesystem.py1206
-rw-r--r--python/src/tcf/services/linenumbers.py264
-rw-r--r--python/src/tcf/services/local/LocatorService.py1614
-rw-r--r--python/src/tcf/services/local/__init__.py20
-rw-r--r--python/src/tcf/services/locator.py188
-rw-r--r--python/src/tcf/services/memory.py606
-rw-r--r--python/src/tcf/services/memorymap.py376
-rw-r--r--python/src/tcf/services/pathmap.py306
-rw-r--r--python/src/tcf/services/processes.py680
-rw-r--r--python/src/tcf/services/processes_v1.py94
-rw-r--r--python/src/tcf/services/registers.py936
-rw-r--r--python/src/tcf/services/remote/BreakpointsProxy.py298
-rw-r--r--python/src/tcf/services/remote/DiagnosticsProxy.py348
-rw-r--r--python/src/tcf/services/remote/DisassemblyProxy.py116
-rw-r--r--python/src/tcf/services/remote/ExpressionsProxy.py268
-rw-r--r--python/src/tcf/services/remote/FileSystemProxy.py1018
-rw-r--r--python/src/tcf/services/remote/LineNumbersProxy.py134
-rw-r--r--python/src/tcf/services/remote/LocatorProxy.py298
-rw-r--r--python/src/tcf/services/remote/MemoryMapProxy.py164
-rw-r--r--python/src/tcf/services/remote/MemoryProxy.py484
-rw-r--r--python/src/tcf/services/remote/PathMapProxy.py112
-rw-r--r--python/src/tcf/services/remote/ProcessesProxy.py430
-rw-r--r--python/src/tcf/services/remote/ProcessesV1Proxy.py64
-rw-r--r--python/src/tcf/services/remote/RegistersProxy.py352
-rw-r--r--python/src/tcf/services/remote/RunControlProxy.py316
-rw-r--r--python/src/tcf/services/remote/StackTraceProxy.py108
-rw-r--r--python/src/tcf/services/remote/StreamsProxy.py292
-rw-r--r--python/src/tcf/services/remote/SymbolsProxy.py242
-rw-r--r--python/src/tcf/services/remote/SysMonitorProxy.py154
-rw-r--r--python/src/tcf/services/remote/TerminalsProxy.py246
-rw-r--r--python/src/tcf/services/runcontrol.py964
-rw-r--r--python/src/tcf/services/stacktrace.py324
-rw-r--r--python/src/tcf/services/streams.py448
-rw-r--r--python/src/tcf/services/symbols.py783
-rw-r--r--python/src/tcf/services/sysmonitor.py804
-rw-r--r--python/src/tcf/services/terminals.py444
-rw-r--r--python/src/tcf/shell.py202
-rw-r--r--python/src/tcf/tests/BasicTests.py1320
-rw-r--r--python/src/tcf/transport.py316
-rw-r--r--python/src/tcf/util/__init__.py20
-rw-r--r--python/src/tcf/util/cache.py540
-rw-r--r--python/src/tcf/util/event.py172
-rw-r--r--python/src/tcf/util/logging.py108
-rw-r--r--python/src/tcf/util/sync.py444
-rw-r--r--python/src/tcf/util/task.py360
58 files changed, 11716 insertions, 11715 deletions
diff --git a/python/.project b/python/.project
index ea91adff9..e46b0ca9a 100644
--- a/python/.project
+++ b/python/.project
@@ -1,17 +1,17 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.eclipse.tcf.python</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.python.pydev.PyDevBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.python.pydev.pythonNature</nature>
- </natures>
-</projectDescription>
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.tcf.python</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
diff --git a/python/src/tcf/EventQueue.py b/python/src/tcf/EventQueue.py
index 0efc5f60c..cc38aa245 100644
--- a/python/src/tcf/EventQueue.py
+++ b/python/src/tcf/EventQueue.py
@@ -1,81 +1,81 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import threading
-import protocol
-
-class EventQueue(object):
-
- def __init__(self, on_shutdown=None):
- self.__thread = threading.Thread(target=self, name="TCF Event Dispatcher")
- self.__thread.daemon = True
- self.__is_waiting = False
- self.__is_shutdown = False
- self.__on_shutdown = on_shutdown
- self.__lock = threading.Condition()
- self.__queue = []
-
- def start(self):
- self.__thread.start()
-
- def shutdown(self):
- try:
- if self.__on_shutdown:
- self.__on_shutdown()
- with self.__lock:
- self.__is_shutdown = True
- if self.__is_waiting:
- self.__is_waiting = False
- self.__lock.notifyAll()
- self.__thread.join()
- except Exception as e:
- protocol.log("Failed to shutdown TCF event dispatch thread", e)
-
- def isShutdown(self):
- with self._lock:
- return self.__is_shutdown
-
- def __error(self, x):
- protocol.log("Unhandled exception in TCF event dispatch", x)
-
- def __call__(self):
- while True:
- try:
- with self.__lock:
- while not self.__queue:
- if self.__is_shutdown: return
- self.__is_waiting = True
- self.__lock.wait()
- r, args, kwargs = self.__queue.pop(0)
- r(*args, **kwargs)
- except Exception as x:
- self.__error(x)
-
- def invokeLater(self, r, *args, **kwargs):
- assert r
- with self.__lock:
- if self.__is_shutdown: raise RuntimeError("TCF event dispatcher has shut down")
- self.__queue.append((r, args, kwargs))
- if self.__is_waiting:
- self.__is_waiting = False
- self.__lock.notifyAll()
-
- def isDispatchThread(self):
- return threading.currentThread() is self.__thread
-
- def getCongestion(self):
- with self.__lock:
- job_cnt = 0
- l0 = job_cnt / 10 - 100
- l1 = len(self.__queue) / 10 - 100
- if l1 > l0: l0 = l1
- if l0 > 100: l0 = 100
- return l0
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading
+import protocol
+
+class EventQueue(object):
+
+ def __init__(self, on_shutdown=None):
+ self.__thread = threading.Thread(target=self, name="TCF Event Dispatcher")
+ self.__thread.daemon = True
+ self.__is_waiting = False
+ self.__is_shutdown = False
+ self.__on_shutdown = on_shutdown
+ self.__lock = threading.Condition()
+ self.__queue = []
+
+ def start(self):
+ self.__thread.start()
+
+ def shutdown(self):
+ try:
+ if self.__on_shutdown:
+ self.__on_shutdown()
+ with self.__lock:
+ self.__is_shutdown = True
+ if self.__is_waiting:
+ self.__is_waiting = False
+ self.__lock.notifyAll()
+ self.__thread.join()
+ except Exception as e:
+ protocol.log("Failed to shutdown TCF event dispatch thread", e)
+
+ def isShutdown(self):
+ with self._lock:
+ return self.__is_shutdown
+
+ def __error(self, x):
+ protocol.log("Unhandled exception in TCF event dispatch", x)
+
+ def __call__(self):
+ while True:
+ try:
+ with self.__lock:
+ while not self.__queue:
+ if self.__is_shutdown: return
+ self.__is_waiting = True
+ self.__lock.wait()
+ r, args, kwargs = self.__queue.pop(0)
+ r(*args, **kwargs)
+ except Exception as x:
+ self.__error(x)
+
+ def invokeLater(self, r, *args, **kwargs):
+ assert r
+ with self.__lock:
+ if self.__is_shutdown: raise RuntimeError("TCF event dispatcher has shut down")
+ self.__queue.append((r, args, kwargs))
+ if self.__is_waiting:
+ self.__is_waiting = False
+ self.__lock.notifyAll()
+
+ def isDispatchThread(self):
+ return threading.currentThread() is self.__thread
+
+ def getCongestion(self):
+ with self.__lock:
+ job_cnt = 0
+ l0 = job_cnt / 10 - 100
+ l1 = len(self.__queue) / 10 - 100
+ if l1 > l0: l0 = l1
+ if l0 > 100: l0 = 100
+ return l0
diff --git a/python/src/tcf/__init__.py b/python/src/tcf/__init__.py
index 5918652db..9978c6234 100644
--- a/python/src/tcf/__init__.py
+++ b/python/src/tcf/__init__.py
@@ -1,63 +1,63 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-TCF - Target Communication Framework
-"""
-
-import types
-import protocol, peer, channel
-from util import task
-
-__all__ = ('connect')
-
-def connect(params, wait=True):
- """Connect to peer. Argument is a string of the form <transport>:<host>:<port>,
- e.g. "TCP:127.0.0.1:1534" """
- if type(params) is types.StringType:
- params = _parse_params(params)
- elif type(params) is not types.DictType:
- raise TypeError("Expected string or dict")
- p = peer.TransientPeer(params)
- if wait:
- c = task.Task(_openChannel, p).get()
- else:
- c = protocol.invokeAndWait(p.openChannel)
- return c
-
-def peers():
- "Return list of discovered remote peers"
- locator = protocol.getLocator()
- if locator:
- return protocol.invokeAndWait(locator.getPeers)
-
-def _openChannel(p, done=None):
- assert protocol.isDispatchThread()
- c = p.openChannel()
- if done is None: return
- class ChannelListener(channel.ChannelListener):
- def onChannelOpened(self):
- c.removeChannelListener(self)
- done(None, c)
- def onChannelClosed(self, error):
- done(error, None)
- c.addChannelListener(ChannelListener())
-
-def _parse_params(paramStr):
- args = paramStr.split(":")
- if len(args) != 3:
- raise ValueError("Expected format: <transport>:<host>:<port>")
- transp, host, port = args
- return {
- peer.ATTR_IP_HOST : host,
- peer.ATTR_IP_PORT : port,
- peer.ATTR_TRANSPORT_NAME : transp
- }
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+TCF - Target Communication Framework
+"""
+
+import types
+import protocol, peer, channel
+from util import task
+
+__all__ = ('connect')
+
+def connect(params, wait=True):
+ """Connect to peer. Argument is a string of the form <transport>:<host>:<port>,
+ e.g. "TCP:127.0.0.1:1534" """
+ if type(params) is types.StringType:
+ params = _parse_params(params)
+ elif type(params) is not types.DictType:
+ raise TypeError("Expected string or dict")
+ p = peer.TransientPeer(params)
+ if wait:
+ c = task.Task(_openChannel, p).get()
+ else:
+ c = protocol.invokeAndWait(p.openChannel)
+ return c
+
+def peers():
+ "Return list of discovered remote peers"
+ locator = protocol.getLocator()
+ if locator:
+ return protocol.invokeAndWait(locator.getPeers)
+
+def _openChannel(p, done=None):
+ assert protocol.isDispatchThread()
+ c = p.openChannel()
+ if done is None: return
+ class ChannelListener(channel.ChannelListener):
+ def onChannelOpened(self):
+ c.removeChannelListener(self)
+ done(None, c)
+ def onChannelClosed(self, error):
+ done(error, None)
+ c.addChannelListener(ChannelListener())
+
+def _parse_params(paramStr):
+ args = paramStr.split(":")
+ if len(args) != 3:
+ raise ValueError("Expected format: <transport>:<host>:<port>")
+ transp, host, port = args
+ return {
+ peer.ATTR_IP_HOST : host,
+ peer.ATTR_IP_PORT : port,
+ peer.ATTR_TRANSPORT_NAME : transp
+ }
diff --git a/python/src/tcf/channel/ChannelProxy.py b/python/src/tcf/channel/ChannelProxy.py
index eca426e3c..dc0802759 100644
--- a/python/src/tcf/channel/ChannelProxy.py
+++ b/python/src/tcf/channel/ChannelProxy.py
@@ -1,97 +1,97 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-ChannelProxy implements forwarding of TCF messages between two channels.
-The class is used to implement Locator service "redirect" command.
-"""
-
-from tcf import channel
-
-class ProxyCommandListener(channel.CommandListener):
- def __init__(self, ch, tokens):
- self.ch = ch
- self.tokens = tokens
- def progress(self, token, data):
- self.ch.sendProgress(self.tokens.get(token), data)
- def result(self, token, data):
- self.ch.sendResult(self.tokens.pop(token, None), data)
- def terminated(self, token, error):
- self.ch.rejectCommand(self.tokens.pop(token, None))
-
-class ChannelProxy(object):
- def __init__(self, x, y):
- #assert not isinstance(x, ChannelLoop)
- #assert not isinstance(y, ChannelLoop)
- self.ch_x = x
- self.ch_y = y
- assert self.ch_x.getState() == channel.STATE_OPEN
- assert self.ch_y.getState() == channel.STATE_OPENING
- self.tokens_x = {}
- self.tokens_y = {}
- cmd_listener_x = ProxyCommandListener(self.ch_x, self.tokens_x)
- cmd_listener_y = ProxyCommandListener(self.ch_y, self.tokens_y)
- proxy = self
-
- class ProxyX(channel.Proxy):
- def onChannelClosed(self, error):
- proxy.closed_x = True
- if proxy.closed_y: return
- if error is None: proxy.ch_y.close()
- else: proxy.ch_y.terminate(error)
- def onCommand(self, token, service, name, data):
- if proxy.closed_y: return
- assert proxy.ch_y.getState() == channel.STATE_OPEN
- s = proxy.ch_y.getRemoteService(service)
- if not s: proxy.ch_x.terminate(IOError("Invalid service name"))
- else: proxy.tokens_x[proxy.ch_y.sendCommand(s, name, data, cmd_listener_x)] = token
- def onEvent(self, service, name, data):
- s = proxy.ch_x.getRemoteService(service)
- if not s: proxy.ch_x.terminate(IOError("Invalid service name"))
- elif not proxy.closed_y: proxy.ch_y.sendEvent(s, name, data)
-
- class ProxyY(channel.Proxy):
- def onChannelClosed(self, error):
- proxy.closed_y = True
- if proxy.closed_x: return
- if error is None: proxy.ch_x.close()
- else: proxy.ch_x.terminate(error)
- def onCommand(self, token, service, name, data):
- if proxy.closed_x: return
- assert proxy.ch_x.getState() == channel.STATE_OPEN
- s = proxy.ch_x.getRemoteService(service)
- if not s: proxy.ch_y.terminate(IOError("Invalid service name"))
- else: proxy.tokens_y[proxy.ch_x.sendCommand(s, name, data, cmd_listener_y)] = token
- def onEvent(self, service, name, data):
- s = proxy.ch_y.getRemoteService(service)
- if not s: proxy.ch_y.terminate(IOError("Invalid service name"))
- elif not proxy.closed_x: proxy.ch_x.sendEvent(s, name, data)
-
- proxy_x = ProxyX()
- proxy_y = ProxyY()
-
- try:
- self.ch_y.setProxy(proxy_y, self.ch_x.getRemoteServices())
- class ChannelListener(channel.ChannelListener):
- def onChannelClosed(self, error):
- proxy.ch_y.removeChannelListener(self)
- if error is None: error = Exception("Channel closed")
- def onChannelOpened(self):
- proxy.ch_y.removeChannelListener(self)
- try:
- proxy.ch_x.setProxy(proxy_x, proxy.ch_y.getRemoteServices())
- except IOError as e:
- proxy.ch_x.terminate(e)
- proxy.ch_y.terminate(e)
- self.ch_y.addChannelListener(ChannelListener())
- except IOError as e:
- self.ch_x.terminate(e)
- self.ch_y.terminate(e)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+ChannelProxy implements forwarding of TCF messages between two channels.
+The class is used to implement Locator service "redirect" command.
+"""
+
+from tcf import channel
+
+class ProxyCommandListener(channel.CommandListener):
+ def __init__(self, ch, tokens):
+ self.ch = ch
+ self.tokens = tokens
+ def progress(self, token, data):
+ self.ch.sendProgress(self.tokens.get(token), data)
+ def result(self, token, data):
+ self.ch.sendResult(self.tokens.pop(token, None), data)
+ def terminated(self, token, error):
+ self.ch.rejectCommand(self.tokens.pop(token, None))
+
+class ChannelProxy(object):
+ def __init__(self, x, y):
+ #assert not isinstance(x, ChannelLoop)
+ #assert not isinstance(y, ChannelLoop)
+ self.ch_x = x
+ self.ch_y = y
+ assert self.ch_x.getState() == channel.STATE_OPEN
+ assert self.ch_y.getState() == channel.STATE_OPENING
+ self.tokens_x = {}
+ self.tokens_y = {}
+ cmd_listener_x = ProxyCommandListener(self.ch_x, self.tokens_x)
+ cmd_listener_y = ProxyCommandListener(self.ch_y, self.tokens_y)
+ proxy = self
+
+ class ProxyX(channel.Proxy):
+ def onChannelClosed(self, error):
+ proxy.closed_x = True
+ if proxy.closed_y: return
+ if error is None: proxy.ch_y.close()
+ else: proxy.ch_y.terminate(error)
+ def onCommand(self, token, service, name, data):
+ if proxy.closed_y: return
+ assert proxy.ch_y.getState() == channel.STATE_OPEN
+ s = proxy.ch_y.getRemoteService(service)
+ if not s: proxy.ch_x.terminate(IOError("Invalid service name"))
+ else: proxy.tokens_x[proxy.ch_y.sendCommand(s, name, data, cmd_listener_x)] = token
+ def onEvent(self, service, name, data):
+ s = proxy.ch_x.getRemoteService(service)
+ if not s: proxy.ch_x.terminate(IOError("Invalid service name"))
+ elif not proxy.closed_y: proxy.ch_y.sendEvent(s, name, data)
+
+ class ProxyY(channel.Proxy):
+ def onChannelClosed(self, error):
+ proxy.closed_y = True
+ if proxy.closed_x: return
+ if error is None: proxy.ch_x.close()
+ else: proxy.ch_x.terminate(error)
+ def onCommand(self, token, service, name, data):
+ if proxy.closed_x: return
+ assert proxy.ch_x.getState() == channel.STATE_OPEN
+ s = proxy.ch_x.getRemoteService(service)
+ if not s: proxy.ch_y.terminate(IOError("Invalid service name"))
+ else: proxy.tokens_y[proxy.ch_x.sendCommand(s, name, data, cmd_listener_y)] = token
+ def onEvent(self, service, name, data):
+ s = proxy.ch_y.getRemoteService(service)
+ if not s: proxy.ch_y.terminate(IOError("Invalid service name"))
+ elif not proxy.closed_x: proxy.ch_x.sendEvent(s, name, data)
+
+ proxy_x = ProxyX()
+ proxy_y = ProxyY()
+
+ try:
+ self.ch_y.setProxy(proxy_y, self.ch_x.getRemoteServices())
+ class ChannelListener(channel.ChannelListener):
+ def onChannelClosed(self, error):
+ proxy.ch_y.removeChannelListener(self)
+ if error is None: error = Exception("Channel closed")
+ def onChannelOpened(self):
+ proxy.ch_y.removeChannelListener(self)
+ try:
+ proxy.ch_x.setProxy(proxy_x, proxy.ch_y.getRemoteServices())
+ except IOError as e:
+ proxy.ch_x.terminate(e)
+ proxy.ch_y.terminate(e)
+ self.ch_y.addChannelListener(ChannelListener())
+ except IOError as e:
+ self.ch_x.terminate(e)
+ self.ch_y.terminate(e)
diff --git a/python/src/tcf/channel/StreamChannel.py b/python/src/tcf/channel/StreamChannel.py
index a572f83ac..9c6d2239a 100644
--- a/python/src/tcf/channel/StreamChannel.py
+++ b/python/src/tcf/channel/StreamChannel.py
@@ -1,130 +1,130 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import types
-from AbstractChannel import AbstractChannel, EOS, EOM
-
-ESC = 3
-
-class StreamChannel(AbstractChannel):
- """
- Abstract channel implementation for stream oriented transport protocols.
-
- StreamChannel implements communication link connecting two end points (peers).
- The channel asynchronously transmits messages: commands, results and events.
-
- StreamChannel uses escape sequences to represent End-Of-Message and End-Of-Stream markers.
-
- Clients can subclass StreamChannel to support particular stream oriented transport (wire) protocol.
- Also, see ChannelTCP for a concrete IChannel implementation that works on top of TCP sockets as a transport.
- """
-
- def __init__(self, remote_peer, local_peer=None):
- super(StreamChannel, self).__init__(remote_peer, local_peer=local_peer)
- self.bin_data_size = 0
- self.buf = bytearray(0x1000)
- self.buf_pos = 0
- self.buf_len = 0
-
- def get(self):
- pass
- def put(self, n):
- pass
-
- def getBuf(self, buf):
- i = 0
- l = len(buf)
- while i < l:
- b = self.get()
- if b < 0:
- if i == 0: return -1
- break
- buf[i] = b
- i += 1
- if i >= self.bin_data_size: break
- return i
-
- def putBuf(self, buf):
- for b in buf: self.put(b & 0xff)
-
- def read(self):
- while True:
- while self.buf_pos >= self.buf_len:
- self.buf_len = self.getBuf(self.buf)
- self.buf_pos = 0
- if self.buf_len < 0: return EOS
- res = self.buf[self.buf_pos] & 0xff
- self.buf_pos += 1
- if self.bin_data_size > 0:
- self.bin_data_size -= 1
- return res
- if res != ESC: return res
- while self.buf_pos >= self.buf_len:
- self.buf_len = self.getBuf(self.buf)
- self.buf_pos = 0
- if self.buf_len < 0: return EOS
- n = self.buf[self.buf_pos] & 0xff
- self.buf_pos += 1
- if n == 0: return ESC
- elif n == 1: return EOM
- elif n == 2: return EOS
- elif n == 3:
- for i in xrange(0, 100000, 7):
- while self.buf_pos >= self.buf_len:
- self.buf_len = self.getBuf(self.buf)
- self.buf_pos = 0
- if self.buf_len < 0: return EOS
- m = self.buf[self.buf_pos] & 0xff
- self.buf_pos += 1
- self.bin_data_size |= (m & 0x7f) << i
- if (m & 0x80) == 0: break
- else:
- if n < 0: return EOS
- assert False
-
- def writeByte(self, n):
- if n == ESC:
- self.put(ESC)
- self.put(0)
- elif n == EOM:
- self.put(ESC)
- self.put(1)
- elif n == EOS:
- self.put(ESC)
- self.put(2)
- else:
- assert n >= 0 and n <= 0xff
- self.put(n)
-
- def write(self, buf):
- t = type(buf)
- if t == types.IntType:
- self.writeByte(buf)
- return
- elif t == types.StringType:
- buf = bytearray(buf)
- if len(buf) > 32 and self.isZeroCopySupported():
- self.put(ESC)
- self.put(3)
- n = len(buf)
- while True:
- if n <= 0x7f:
- self.put(n)
- break
- self.put((n & 0x7f) | 0x80)
- n >>= 7
- self.putBuf(buf)
- else:
- for b in buf:
- n = b & 0xff
- self.put(n)
- if n == ESC:
- self.put(0)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import types
+from AbstractChannel import AbstractChannel, EOS, EOM
+
+ESC = 3
+
+class StreamChannel(AbstractChannel):
+ """
+ Abstract channel implementation for stream oriented transport protocols.
+
+ StreamChannel implements communication link connecting two end points (peers).
+ The channel asynchronously transmits messages: commands, results and events.
+
+ StreamChannel uses escape sequences to represent End-Of-Message and End-Of-Stream markers.
+
+ Clients can subclass StreamChannel to support particular stream oriented transport (wire) protocol.
+ Also, see ChannelTCP for a concrete IChannel implementation that works on top of TCP sockets as a transport.
+ """
+
+ def __init__(self, remote_peer, local_peer=None):
+ super(StreamChannel, self).__init__(remote_peer, local_peer=local_peer)
+ self.bin_data_size = 0
+ self.buf = bytearray(0x1000)
+ self.buf_pos = 0
+ self.buf_len = 0
+
+ def get(self):
+ pass
+ def put(self, n):
+ pass
+
+ def getBuf(self, buf):
+ i = 0
+ l = len(buf)
+ while i < l:
+ b = self.get()
+ if b < 0:
+ if i == 0: return -1
+ break
+ buf[i] = b
+ i += 1
+ if i >= self.bin_data_size: break
+ return i
+
+ def putBuf(self, buf):
+ for b in buf: self.put(b & 0xff)
+
+ def read(self):
+ while True:
+ while self.buf_pos >= self.buf_len:
+ self.buf_len = self.getBuf(self.buf)
+ self.buf_pos = 0
+ if self.buf_len < 0: return EOS
+ res = self.buf[self.buf_pos] & 0xff
+ self.buf_pos += 1
+ if self.bin_data_size > 0:
+ self.bin_data_size -= 1
+ return res
+ if res != ESC: return res
+ while self.buf_pos >= self.buf_len:
+ self.buf_len = self.getBuf(self.buf)
+ self.buf_pos = 0
+ if self.buf_len < 0: return EOS
+ n = self.buf[self.buf_pos] & 0xff
+ self.buf_pos += 1
+ if n == 0: return ESC
+ elif n == 1: return EOM
+ elif n == 2: return EOS
+ elif n == 3:
+ for i in xrange(0, 100000, 7):
+ while self.buf_pos >= self.buf_len:
+ self.buf_len = self.getBuf(self.buf)
+ self.buf_pos = 0
+ if self.buf_len < 0: return EOS
+ m = self.buf[self.buf_pos] & 0xff
+ self.buf_pos += 1
+ self.bin_data_size |= (m & 0x7f) << i
+ if (m & 0x80) == 0: break
+ else:
+ if n < 0: return EOS
+ assert False
+
+ def writeByte(self, n):
+ if n == ESC:
+ self.put(ESC)
+ self.put(0)
+ elif n == EOM:
+ self.put(ESC)
+ self.put(1)
+ elif n == EOS:
+ self.put(ESC)
+ self.put(2)
+ else:
+ assert n >= 0 and n <= 0xff
+ self.put(n)
+
+ def write(self, buf):
+ t = type(buf)
+ if t == types.IntType:
+ self.writeByte(buf)
+ return
+ elif t == types.StringType:
+ buf = bytearray(buf)
+ if len(buf) > 32 and self.isZeroCopySupported():
+ self.put(ESC)
+ self.put(3)
+ n = len(buf)
+ while True:
+ if n <= 0x7f:
+ self.put(n)
+ break
+ self.put((n & 0x7f) | 0x80)
+ n >>= 7
+ self.putBuf(buf)
+ else:
+ for b in buf:
+ n = b & 0xff
+ self.put(n)
+ if n == ESC:
+ self.put(0)
diff --git a/python/src/tcf/channel/__init__.py b/python/src/tcf/channel/__init__.py
index c6c47974a..8fd0031d1 100644
--- a/python/src/tcf/channel/__init__.py
+++ b/python/src/tcf/channel/__init__.py
@@ -1,189 +1,189 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import cStringIO, json, binascii, types
-
-# channel states
-STATE_OPENING = 0
-STATE_OPEN = 1
-STATE_CLOSED = 2
-
-class TraceListener(object):
- def onMessageReceived(self, type, token, service, name, data):
- pass
-
- def onMessageSent(self, type, token, service, name, data):
- pass
-
- def onChannelClosed(self, error):
- pass
-
-def Proxy(object):
- def onCommand(self, token, service, name, data):
- pass
-
- def onEvent(self, service, name, data):
- pass
-
- def onChannelClosed(self, error):
- pass
-
-_token_cnt = 0
-class Token(object):
- def __init__(self, id=None, listener=None):
- if id is None:
- global _token_cnt
- id = str(_token_cnt)
- _token_cnt += 1
- else:
- id = str(id)
- self.id = id
- self.listener = listener
- def getID(self):
- return self.id
- def getListener(self):
- return self.listener
- def cancel(self):
- return False
-
-class ChannelListener(object):
- """
- Channel listener interface.
- """
-
- def onChannelOpened(self):
- """
- Called when a channel is opened or redirected.
- """
- pass
-
- def onChannelClosed(self, error):
- """
- Called when channel closed. If it is closed because of an error,
- 'error' parameter will describe the error. 'error' is None if channel
- is closed normally by calling Channel.close().
- @param error - channel exception or None
- """
- pass
-
- def congestionLevel(self, level):
- """
- Notifies listeners about channel out-bound traffic congestion level changes.
- When level > 0 client should delay sending more messages.
- @param level - current congestion level
- """
- pass
-
-class EventListener(object):
- """
- A generic interface for service event listener.
- Services usually define a service specific event listener interface,
- which is implemented using this generic listener.
- Clients should user service specific listener interface,
- unless no such interface is defined.
- """
- svc_name = "<unknown>"
- def event(self, name, data):
- """
- Called when service event message is received
- @param name - event name
- @param data - event arguments encoded as bytearray
- """
- pass
-
-class CommandServer(object):
- """
- Command server interface.
- This interface is to be implemented by service providers.
- """
- def command(self, token, name, data):
- """
- Called every time a command is received from remote peer.
- @param token - command handle
- @param name - command name
- @param data - command arguments encoded into array of bytes
- """
- pass
-
-class CommandListener(object):
- """
- Command listener interface. Clients implement this interface to
- receive command results.
- """
- def progress(self, token, data):
- """
- Called when progress message (intermediate result) is received
- from remote peer.
- @param token - command handle
- @param data - progress message arguments encoded into array of bytes
- """
- pass
- def result(self, token, data):
- """
- Called when command result received from remote peer.
- @param token - command handle
- @param data - command result message arguments encoded into array of bytes
- """
- pass
- def terminated(self, token, error):
- """
- Called when command is terminated because communication channel was closed or
- command is not recognized by remote peer.
- @param token - command handle
- @param error - exception that forced the channel to close
- """
- pass
-
-def toJSONSequence(args):
- if args is None:
- return None
- buf = cStringIO.StringIO()
- for arg in args:
- json.dump(arg, buf, separators=(',', ':'), cls=TCFJSONEncoder)
- buf.write('\0')
- return buf.getvalue()
-
-def fromJSONSequence(bytes):
- if bytes[-1] == 0:
- del bytes[-1]
- str = bytes.decode("UTF-8")
- parts = str.split('\0')
- objects = []
- for part in parts:
- if part:
- objects.append(json.loads(part))
- else:
- objects.append(None)
- return objects
-
-def dumpJSONObject(object, buf):
- json.dump(object, buf, separators=(',', ':'), cls=TCFJSONEncoder)
-
-def toByteArray(data):
- if data is None: return None
- t = type(data)
- if t is bytearray: return data
- elif t is str:
- return binascii.a2b_base64(data)
- elif t is unicode:
- return binascii.a2b_base64(str(data))
- raise TypeError(str(t))
-
-class TCFJSONEncoder(json.JSONEncoder):
- def default(self, o):
- if isinstance(o, bytearray):
- return binascii.b2a_base64(o)[:-1]
- elif hasattr(o, '__json__'):
- return o.__json__()
- elif hasattr(o, '__iter__'):
- return tuple(o)
- else:
- json.JSONEncoder.default(self, o)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import cStringIO, json, binascii, types
+
+# channel states
+STATE_OPENING = 0
+STATE_OPEN = 1
+STATE_CLOSED = 2
+
+class TraceListener(object):
+ def onMessageReceived(self, type, token, service, name, data):
+ pass
+
+ def onMessageSent(self, type, token, service, name, data):
+ pass
+
+ def onChannelClosed(self, error):
+ pass
+
+def Proxy(object):
+ def onCommand(self, token, service, name, data):
+ pass
+
+ def onEvent(self, service, name, data):
+ pass
+
+ def onChannelClosed(self, error):
+ pass
+
+_token_cnt = 0
+class Token(object):
+ def __init__(self, id=None, listener=None):
+ if id is None:
+ global _token_cnt
+ id = str(_token_cnt)
+ _token_cnt += 1
+ else:
+ id = str(id)
+ self.id = id
+ self.listener = listener
+ def getID(self):
+ return self.id
+ def getListener(self):
+ return self.listener
+ def cancel(self):
+ return False
+
+class ChannelListener(object):
+ """
+ Channel listener interface.
+ """
+
+ def onChannelOpened(self):
+ """
+ Called when a channel is opened or redirected.
+ """
+ pass
+
+ def onChannelClosed(self, error):
+ """
+ Called when channel closed. If it is closed because of an error,
+ 'error' parameter will describe the error. 'error' is None if channel
+ is closed normally by calling Channel.close().
+ @param error - channel exception or None
+ """
+ pass
+
+ def congestionLevel(self, level):
+ """
+ Notifies listeners about channel out-bound traffic congestion level changes.
+ When level > 0 client should delay sending more messages.
+ @param level - current congestion level
+ """
+ pass
+
+class EventListener(object):
+ """
+ A generic interface for service event listener.
+ Services usually define a service specific event listener interface,
+ which is implemented using this generic listener.
+ Clients should user service specific listener interface,
+ unless no such interface is defined.
+ """
+ svc_name = "<unknown>"
+ def event(self, name, data):
+ """
+ Called when service event message is received
+ @param name - event name
+ @param data - event arguments encoded as bytearray
+ """
+ pass
+
+class CommandServer(object):
+ """
+ Command server interface.
+ This interface is to be implemented by service providers.
+ """
+ def command(self, token, name, data):
+ """
+ Called every time a command is received from remote peer.
+ @param token - command handle
+ @param name - command name
+ @param data - command arguments encoded into array of bytes
+ """
+ pass
+
+class CommandListener(object):
+ """
+ Command listener interface. Clients implement this interface to
+ receive command results.
+ """
+ def progress(self, token, data):
+ """
+ Called when progress message (intermediate result) is received
+ from remote peer.
+ @param token - command handle
+ @param data - progress message arguments encoded into array of bytes
+ """
+ pass
+ def result(self, token, data):
+ """
+ Called when command result received from remote peer.
+ @param token - command handle
+ @param data - command result message arguments encoded into array of bytes
+ """
+ pass
+ def terminated(self, token, error):
+ """
+ Called when command is terminated because communication channel was closed or
+ command is not recognized by remote peer.
+ @param token - command handle
+ @param error - exception that forced the channel to close
+ """
+ pass
+
+def toJSONSequence(args):
+ if args is None:
+ return None
+ buf = cStringIO.StringIO()
+ for arg in args:
+ json.dump(arg, buf, separators=(',', ':'), cls=TCFJSONEncoder)
+ buf.write('\0')
+ return buf.getvalue()
+
+def fromJSONSequence(bytes):
+ if bytes[-1] == 0:
+ del bytes[-1]
+ str = bytes.decode("UTF-8")
+ parts = str.split('\0')
+ objects = []
+ for part in parts:
+ if part:
+ objects.append(json.loads(part))
+ else:
+ objects.append(None)
+ return objects
+
+def dumpJSONObject(object, buf):
+ json.dump(object, buf, separators=(',', ':'), cls=TCFJSONEncoder)
+
+def toByteArray(data):
+ if data is None: return None
+ t = type(data)
+ if t is bytearray: return data
+ elif t is str:
+ return binascii.a2b_base64(data)
+ elif t is unicode:
+ return binascii.a2b_base64(str(data))
+ raise TypeError(str(t))
+
+class TCFJSONEncoder(json.JSONEncoder):
+ def default(self, o):
+ if isinstance(o, bytearray):
+ return binascii.b2a_base64(o)[:-1]
+ elif hasattr(o, '__json__'):
+ return o.__json__()
+ elif hasattr(o, '__iter__'):
+ return tuple(o)
+ else:
+ json.JSONEncoder.default(self, o)
diff --git a/python/src/tcf/errors.py b/python/src/tcf/errors.py
index 79c2706a9..947590167 100644
--- a/python/src/tcf/errors.py
+++ b/python/src/tcf/errors.py
@@ -1,161 +1,161 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http:#www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import cStringIO, time, types
-
-# Error report attribute names
-ERROR_CODE = "Code" # integer
-ERROR_TIME = "Time" # integer
-ERROR_SERVICE = "Service" # string
-ERROR_FORMAT = "Format" # string
-ERROR_PARAMS = "Params" # array
-ERROR_SEVERITY = "Severity" # integer
-ERROR_ALT_CODE = "AltCode" # integer
-ERROR_ALT_ORG = "AltOrg" # string
-ERROR_CAUSED_BY = "CausedBy" # object
-
-# Error severity codes
-SEVERITY_ERROR = 0
-SEVERITY_WARNING = 1
-SEVERITY_FATAL = 2
-
-# Error code ranges
-# Standard TCF code range */
-CODE_STD_MIN = 0
-CODE_STD_MAX = 0xffff
-
-# Service specific codes. Decoding requires service ID. */
-CODE_SERVICE_SPECIFIC_MIN = 0x10000
-CODE_SERVICE_SPECIFIC_MAX = 0x1ffff
-
-# Reserved codes - will never be used by the TCF standard */
-CODE_RESERVED_MIN = 0x20000
-CODE_RESERVED_MAX = 0x2ffff
-
-# Standard TCF error codes
-TCF_ERROR_OTHER = 1
-TCF_ERROR_JSON_SYNTAX = 2
-TCF_ERROR_PROTOCOL = 3
-TCF_ERROR_BUFFER_OVERFLOW = 4
-TCF_ERROR_CHANNEL_CLOSED = 5
-TCF_ERROR_COMMAND_CANCELLED = 6
-TCF_ERROR_UNKNOWN_PEER = 7
-TCF_ERROR_BASE64 = 8
-TCF_ERROR_EOF = 9
-TCF_ERROR_ALREADY_STOPPED = 10
-TCF_ERROR_ALREADY_EXITED = 11
-TCF_ERROR_ALREADY_RUNNING = 12
-TCF_ERROR_ALREADY_ATTACHED = 13
-TCF_ERROR_IS_RUNNING = 14
-TCF_ERROR_INV_DATA_SIZE = 15
-TCF_ERROR_INV_CONTEXT = 16
-TCF_ERROR_INV_ADDRESS = 17
-TCF_ERROR_INV_EXPRESSION = 18
-TCF_ERROR_INV_FORMAT = 19
-TCF_ERROR_INV_NUMBER = 20
-TCF_ERROR_INV_DWARF = 21
-TCF_ERROR_SYM_NOT_FOUND = 22
-TCF_ERROR_UNSUPPORTED = 23
-TCF_ERROR_INV_DATA_TYPE = 24
-TCF_ERROR_INV_COMMAND = 25
-TCF_ERROR_INV_TRANSPORT = 26
-TCF_ERROR_CACHE_MISS = 27
-TCF_ERROR_NOT_ACTIVE = 28
-
-_timestamp_format = "%Y-%m-%d %H:%M:%S"
-
-class ErrorReport(Exception):
- def __init__(self, msg, attrs):
- super(ErrorReport, self).__init__(msg)
- if type(attrs) is types.IntType:
- attrs = {
- ERROR_CODE : attrs,
- ERROR_TIME : int(time.time() * 1000),
- ERROR_FORMAT : msg,
- ERROR_SEVERITY : SEVERITY_ERROR
- }
- self.attrs = attrs
- caused_by = attrs.get(ERROR_CAUSED_BY)
- if caused_by:
- map = caused_by
- bf = cStringIO.StringIO()
- bf.write("TCF error report:")
- bf.write('\n')
- appendErrorProps(bf, map)
- self.caused_by = ErrorReport(bf.getvalue(), map)
-
- def getErrorCode(self):
- return self.attrs.get(ERROR_CODE) or 0
-
- def getAltCode(self):
- return self.attrs.get(ERROR_ALT_CODE) or 0
-
- def getAltOrg(self):
- return self.attrs.get(ERROR_ALT_ORG)
-
- def getAttributes(self):
- return self.attrs
-
-
-def toErrorString(data):
- if not data: return None
- map = data
- fmt = map.get(ERROR_FORMAT)
- if fmt:
- c = map.get(ERROR_PARAMS)
- if c: return fmt.format(c)
- return fmt
- code = map.get(ERROR_CODE)
- if code is not None:
- if code == TCF_ERROR_OTHER:
- alt_org = map.get(ERROR_ALT_ORG)
- alt_code = map.get(ERROR_ALT_CODE)
- if alt_org and alt_code:
- return "%s Error %d" % (alt_org, alt_code)
- return "TCF Error %d" % code
- return "Invalid error report format"
-
-def appendErrorProps(bf, map):
- timeVal = map.get(ERROR_TIME)
- code = map.get(ERROR_CODE)
- service = map.get(ERROR_SERVICE)
- severity = map.get(ERROR_SEVERITY)
- alt_code = map.get(ERROR_ALT_CODE)
- alt_org = map.get(ERROR_ALT_ORG)
- if timeVal:
- bf.write('\n')
- bf.write("Time: ")
- bf.write(time.strftime(_timestamp_format, time.localtime(timeVal/1000.)))
- if severity:
- bf.write('\n')
- bf.write("Severity: ")
- if severity == SEVERITY_ERROR: bf.write("Error")
- elif severity == SEVERITY_FATAL: bf.write("Fatal")
- elif severity == SEVERITY_WARNING: bf.write("Warning")
- else: bf.write("Unknown")
- bf.write('\n')
- bf.write("Error text: ")
- bf.write(toErrorString(map))
- bf.write('\n')
- bf.write("Error code: ")
- bf.write(str(code))
- if service:
- bf.write('\n')
- bf.write("Service: ")
- bf.write(service)
- if alt_code:
- bf.write('\n')
- bf.write("Alt code: ")
- bf.write(str(alt_code))
- if alt_org:
- bf.write('\n')
- bf.write("Alt org: ")
- bf.write(alt_org)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http:#www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import cStringIO, time, types
+
+# Error report attribute names
+ERROR_CODE = "Code" # integer
+ERROR_TIME = "Time" # integer
+ERROR_SERVICE = "Service" # string
+ERROR_FORMAT = "Format" # string
+ERROR_PARAMS = "Params" # array
+ERROR_SEVERITY = "Severity" # integer
+ERROR_ALT_CODE = "AltCode" # integer
+ERROR_ALT_ORG = "AltOrg" # string
+ERROR_CAUSED_BY = "CausedBy" # object
+
+# Error severity codes
+SEVERITY_ERROR = 0
+SEVERITY_WARNING = 1
+SEVERITY_FATAL = 2
+
+# Error code ranges
+# Standard TCF code range */
+CODE_STD_MIN = 0
+CODE_STD_MAX = 0xffff
+
+# Service specific codes. Decoding requires service ID. */
+CODE_SERVICE_SPECIFIC_MIN = 0x10000
+CODE_SERVICE_SPECIFIC_MAX = 0x1ffff
+
+# Reserved codes - will never be used by the TCF standard */
+CODE_RESERVED_MIN = 0x20000
+CODE_RESERVED_MAX = 0x2ffff
+
+# Standard TCF error codes
+TCF_ERROR_OTHER = 1
+TCF_ERROR_JSON_SYNTAX = 2
+TCF_ERROR_PROTOCOL = 3
+TCF_ERROR_BUFFER_OVERFLOW = 4
+TCF_ERROR_CHANNEL_CLOSED = 5
+TCF_ERROR_COMMAND_CANCELLED = 6
+TCF_ERROR_UNKNOWN_PEER = 7
+TCF_ERROR_BASE64 = 8
+TCF_ERROR_EOF = 9
+TCF_ERROR_ALREADY_STOPPED = 10
+TCF_ERROR_ALREADY_EXITED = 11
+TCF_ERROR_ALREADY_RUNNING = 12
+TCF_ERROR_ALREADY_ATTACHED = 13
+TCF_ERROR_IS_RUNNING = 14
+TCF_ERROR_INV_DATA_SIZE = 15
+TCF_ERROR_INV_CONTEXT = 16
+TCF_ERROR_INV_ADDRESS = 17
+TCF_ERROR_INV_EXPRESSION = 18
+TCF_ERROR_INV_FORMAT = 19
+TCF_ERROR_INV_NUMBER = 20
+TCF_ERROR_INV_DWARF = 21
+TCF_ERROR_SYM_NOT_FOUND = 22
+TCF_ERROR_UNSUPPORTED = 23
+TCF_ERROR_INV_DATA_TYPE = 24
+TCF_ERROR_INV_COMMAND = 25
+TCF_ERROR_INV_TRANSPORT = 26
+TCF_ERROR_CACHE_MISS = 27
+TCF_ERROR_NOT_ACTIVE = 28
+
+_timestamp_format = "%Y-%m-%d %H:%M:%S"
+
+class ErrorReport(Exception):
+ def __init__(self, msg, attrs):
+ super(ErrorReport, self).__init__(msg)
+ if type(attrs) is types.IntType:
+ attrs = {
+ ERROR_CODE : attrs,
+ ERROR_TIME : int(time.time() * 1000),
+ ERROR_FORMAT : msg,
+ ERROR_SEVERITY : SEVERITY_ERROR
+ }
+ self.attrs = attrs
+ caused_by = attrs.get(ERROR_CAUSED_BY)
+ if caused_by:
+ map = caused_by
+ bf = cStringIO.StringIO()
+ bf.write("TCF error report:")
+ bf.write('\n')
+ appendErrorProps(bf, map)
+ self.caused_by = ErrorReport(bf.getvalue(), map)
+
+ def getErrorCode(self):
+ return self.attrs.get(ERROR_CODE) or 0
+
+ def getAltCode(self):
+ return self.attrs.get(ERROR_ALT_CODE) or 0
+
+ def getAltOrg(self):
+ return self.attrs.get(ERROR_ALT_ORG)
+
+ def getAttributes(self):
+ return self.attrs
+
+
+def toErrorString(data):
+ if not data: return None
+ map = data
+ fmt = map.get(ERROR_FORMAT)
+ if fmt:
+ c = map.get(ERROR_PARAMS)
+ if c: return fmt.format(c)
+ return fmt
+ code = map.get(ERROR_CODE)
+ if code is not None:
+ if code == TCF_ERROR_OTHER:
+ alt_org = map.get(ERROR_ALT_ORG)
+ alt_code = map.get(ERROR_ALT_CODE)
+ if alt_org and alt_code:
+ return "%s Error %d" % (alt_org, alt_code)
+ return "TCF Error %d" % code
+ return "Invalid error report format"
+
+def appendErrorProps(bf, map):
+ timeVal = map.get(ERROR_TIME)
+ code = map.get(ERROR_CODE)
+ service = map.get(ERROR_SERVICE)
+ severity = map.get(ERROR_SEVERITY)
+ alt_code = map.get(ERROR_ALT_CODE)
+ alt_org = map.get(ERROR_ALT_ORG)
+ if timeVal:
+ bf.write('\n')
+ bf.write("Time: ")
+ bf.write(time.strftime(_timestamp_format, time.localtime(timeVal/1000.)))
+ if severity:
+ bf.write('\n')
+ bf.write("Severity: ")
+ if severity == SEVERITY_ERROR: bf.write("Error")
+ elif severity == SEVERITY_FATAL: bf.write("Fatal")
+ elif severity == SEVERITY_WARNING: bf.write("Warning")
+ else: bf.write("Unknown")
+ bf.write('\n')
+ bf.write("Error text: ")
+ bf.write(toErrorString(map))
+ bf.write('\n')
+ bf.write("Error code: ")
+ bf.write(str(code))
+ if service:
+ bf.write('\n')
+ bf.write("Service: ")
+ bf.write(service)
+ if alt_code:
+ bf.write('\n')
+ bf.write("Alt code: ")
+ bf.write(str(alt_code))
+ if alt_org:
+ bf.write('\n')
+ bf.write("Alt org: ")
+ bf.write(alt_org)
diff --git a/python/src/tcf/peer.py b/python/src/tcf/peer.py
index f93092001..85d595d96 100644
--- a/python/src/tcf/peer.py
+++ b/python/src/tcf/peer.py
@@ -1,274 +1,274 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Both hosts and targets are represented by objects
-implementing IPeer interface. A peer can act as host or
-target depending on services it implements.
-List of currently known peers can be retrieved by
-calling Locator.getPeers()
-
-A TCF agent houses one or more service managers. A service manager has a one or more
-services to expose to the world. The service manager creates one or more peers
-to represent itself, one for every access path the agent is
-reachable by. For example, in agents accessible via TCP/IP, the
-service manger would create a peer for every subnet it wants to participate in.
-All peers of particular service manager represent identical sets of services.
-"""
-
-import os, time, json
-from tcf import protocol, transport, services
-from tcf.services import locator
-
-# Peer unique ID
-ATTR_ID = "ID"
-
-# Unique ID of service manager that is represented by this peer
-ATTR_SERVICE_MANAGER_ID = "ServiceManagerID"
-
-# Agent unique ID
-ATTR_AGENT_ID = "AgentID"
-
-# Peer name
-ATTR_NAME = "Name"
-
-# Name of the peer operating system
-ATTR_OS_NAME = "OSName"
-
-# Transport name, for example TCP, SSL
-ATTR_TRANSPORT_NAME = "TransportName"
-
-# If present, indicates that the peer can forward traffic to other peers
-ATTR_PROXY = "Proxy"
-
-# Host DNS name or IP address
-ATTR_IP_HOST = "Host"
-
-# Optional list of host aliases
-ATTR_IP_ALIASES = "Aliases"
-
-# Optional list of host addresses
-ATTR_IP_ADDRESSES = "Addresses"
-
-# IP port number, must be decimal number
-ATTR_IP_PORT = "Port"
-
-
-class Peer(object):
- def __init__(self, attrs):
- self.attrs = attrs
- def getAttributes(self):
- """@return map of peer attributes"""
- return self.attrs
-
- def getID(self):
- """@return peer unique ID, same as getAttributes().get(ATTR_ID)"""
- return self.attrs.get(ATTR_ID)
-
- def getServiceManagerID(self):
- """@return service manager unique ID, same as getAttributes().get(ATTR_SERVICE_MANAGER_ID)"""
- assert protocol.isDispatchThread()
- return self.attrs.get(ATTR_SERVICE_MANAGER_ID)
-
- def getAgentID(self):
- """@return agent unique ID, same as getAttributes().get(ATTR_AGENT_ID)"""
- assert protocol.isDispatchThread()
- return self.attrs.get(ATTR_AGENT_ID)
-
- def getName(self):
- """@return peer name, same as getAttributes().get(ATTR_NAME)"""
- return self.attrs.get(ATTR_NAME)
-
- def getOSName(self):
- """@return agent OS name, same as getAttributes().get(ATTR_OS_NAME)"""
- return self.attrs.get(ATTR_OS_NAME)
-
- def getTransportName(self):
- """@return transport name, same as getAttributes().get(ATTR_TRANSPORT_NAME)"""
- return self.attrs.get(ATTR_TRANSPORT_NAME)
-
- def openChannel(self):
- """Open channel to communicate with this peer.
- Note: the channel is not fully open yet when this method returns.
- Its state is channel.STATE_OPENING.
- Protocol.ChannelOpenListener and IChannel.IChannelListener listeners will be called when
- the channel will change state to open or closed.
- Clients are supposed to register IChannel.IChannelListener right after calling openChannel(), or,
- at least, in same dispatch cycle. For example:
- channel = peer.openChannel()
- channel.addChannelListener(...)
- """
- raise RuntimeError("Abstract method")
-
-
-class TransientPeer(Peer):
- """
- Transient implementation of IPeer interface.
- Objects of this class are not tracked by Locator service.
- See AbstractPeer for IPeer objects that should go into the Locator table.
- """
- def __init__(self, attrs):
- self.rw_attrs = {}
- self.rw_attrs.update(attrs)
- # TODO readonly map
- ro_attrs = {}
- ro_attrs.update(self.rw_attrs)
- super(TransientPeer, self).__init__(ro_attrs)
-
- def openChannel(self):
- return transport.openChannel(self)
-
-class LocalPeer(TransientPeer):
- """
- LocalPeer object represents local end-point of TCF communication channel.
- There should be exactly one such object in a TCF agent.
- The object can be used to open a loop-back communication channel that allows
- the agent to access its own services same way as remote services.
- Note that "local" here is relative to the agent, and not same as in "local host".
- """
- def __init__(self):
- super(LocalPeer, self).__init__(self.createAttributes())
-
- def createAttributes(self):
- attrs = {
- ATTR_ID : "TCFLocal",
- ATTR_SERVICE_MANAGER_ID : services.getServiceManagerID(),
- ATTR_AGENT_ID : protocol.getAgentID(),
- ATTR_NAME : "Local Peer",
- ATTR_OS_NAME : os.name,
- ATTR_TRANSPORT_NAME : "Loop"
- }
- return attrs;
-
-class AbstractPeer(TransientPeer):
- """
- Abstract implementation of IPeer interface.
- Objects of this class are stored in Locator service peer table.
- The class implements sending notification events to Locator listeners.
- See TransientPeer for IPeer objects that are not stored in the Locator table.
- """
-
- last_heart_beat_time = 0
-
- def __init__(self, attrs):
- super(AbstractPeer, self).__init__(attrs)
- assert protocol.isDispatchThread()
- id = self.getID()
- assert id
- peers = protocol.getLocator().getPeers()
- if isinstance(peers.get(id), RemotePeer):
- peers.get(id).dispose()
- assert id not in peers
- peers[id] = self
- self.sendPeerAddedEvent()
-
- def dispose(self):
- assert protocol.isDispatchThread()
- id = self.getID()
- assert id
- peers = protocol.getLocator().getPeers()
- assert peers.get(id) == self
- del peers[id]
- self.sendPeerRemovedEvent()
-
- def onChannelTerminated(self):
- # A channel to this peer was terminated:
- # not delaying next heart beat helps client to recover much faster.
- self.last_heart_beat_time = 0
-
- def updateAttributes(self, attrs):
- equ = True
- assert attrs.get(ATTR_ID) == self.rw_attrs.get(ATTR_ID)
- for key in self.rw_attrs.keys():
- if self.rw_attrs.get(key) != attrs.get(key):
- equ = False
- break
- for key in attrs.keys():
- if attrs.get(key) != self.rw_attrs.get(key):
- equ = False
- break
- timeVal = int(time.time() * 1000)
- if not equ:
- self.rw_attrs.clear()
- self.rw_attrs.update(attrs)
- for l in protocol.getLocator().getListeners():
- try:
- l.peerChanged(self)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- try:
- args = [self.rw_attrs]
- protocol.sendEvent(locator.NAME, "peerChanged", json.dumps(args))
- except IOError as x:
- protocol.log("Locator: failed to send 'peerChanged' event", x)
- self.last_heart_beat_time = timeVal
- elif self.last_heart_beat_time + locator.DATA_RETENTION_PERIOD / 4 < timeVal:
- for l in protocol.getLocator().getListeners():
- try:
- l.peerHeartBeat(attrs.get(ATTR_ID))
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- try:
- args = [self.rw_attrs.get(ATTR_ID)]
- protocol.sendEvent(locator.NAME, "peerHeartBeat", json.dumps(args))
- except IOError as x:
- protocol.log("Locator: failed to send 'peerHeartBeat' event", x)
- self.last_heart_beat_time = timeVal
-
- def sendPeerAddedEvent(self):
- for l in protocol.getLocator().getListeners():
- try:
- l.peerAdded(self)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- try:
- args = [self.rw_attrs]
- protocol.sendEvent(locator.NAME, "peerAdded", json.dumps(args))
- except IOError as x:
- protocol.log("Locator: failed to send 'peerAdded' event", x)
- self.last_heart_beat_time = int(time.time() * 1000)
-
- def sendPeerRemovedEvent(self):
- for l in protocol.getLocator().getListeners():
- try:
- l.peerRemoved(self.rw_attrs.get(ATTR_ID))
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- try:
- args = [self.rw_attrs.get(ATTR_ID)]
- protocol.sendEvent(locator.NAME, "peerRemoved", json.dumps(args))
- except IOError as x:
- protocol.log("Locator: failed to send 'peerRemoved' event", x)
-
-
-class RemotePeer(AbstractPeer):
- """
- RemotePeer objects represent TCF agents that Locator service discovered on local network.
- This includes both local host agents and remote host agents.
- Note that "remote peer" means any peer accessible over network,
- it does not imply the agent is running on a "remote host".
- If an agent binds multiple network interfaces or multiple ports, it can be represented by
- multiple RemotePeer objects - one per each network address/port combination.
- RemotePeer objects life cycle is managed by Locator service.
- """
-
- last_update_time = 0
-
- def __init__(self, attrs):
- super(RemotePeer, self).__init__(attrs)
- self.last_update_time = int(time.time() * 1000)
-
- def updateAttributes(self, attrs):
- super(RemotePeer, self).updateAttributes(attrs)
- self.last_update_time = int(time.time() * 1000)
-
- def getLastUpdateTime(self):
- return self.last_update_time
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Both hosts and targets are represented by objects
+implementing IPeer interface. A peer can act as host or
+target depending on services it implements.
+List of currently known peers can be retrieved by
+calling Locator.getPeers()
+
+A TCF agent houses one or more service managers. A service manager has a one or more
+services to expose to the world. The service manager creates one or more peers
+to represent itself, one for every access path the agent is
+reachable by. For example, in agents accessible via TCP/IP, the
+service manger would create a peer for every subnet it wants to participate in.
+All peers of particular service manager represent identical sets of services.
+"""
+
+import os, time, json
+from tcf import protocol, transport, services
+from tcf.services import locator
+
+# Peer unique ID
+ATTR_ID = "ID"
+
+# Unique ID of service manager that is represented by this peer
+ATTR_SERVICE_MANAGER_ID = "ServiceManagerID"
+
+# Agent unique ID
+ATTR_AGENT_ID = "AgentID"
+
+# Peer name
+ATTR_NAME = "Name"
+
+# Name of the peer operating system
+ATTR_OS_NAME = "OSName"
+
+# Transport name, for example TCP, SSL
+ATTR_TRANSPORT_NAME = "TransportName"
+
+# If present, indicates that the peer can forward traffic to other peers
+ATTR_PROXY = "Proxy"
+
+# Host DNS name or IP address
+ATTR_IP_HOST = "Host"
+
+# Optional list of host aliases
+ATTR_IP_ALIASES = "Aliases"
+
+# Optional list of host addresses
+ATTR_IP_ADDRESSES = "Addresses"
+
+# IP port number, must be decimal number
+ATTR_IP_PORT = "Port"
+
+
+class Peer(object):
+ def __init__(self, attrs):
+ self.attrs = attrs
+ def getAttributes(self):
+ """@return map of peer attributes"""
+ return self.attrs
+
+ def getID(self):
+ """@return peer unique ID, same as getAttributes().get(ATTR_ID)"""
+ return self.attrs.get(ATTR_ID)
+
+ def getServiceManagerID(self):
+ """@return service manager unique ID, same as getAttributes().get(ATTR_SERVICE_MANAGER_ID)"""
+ assert protocol.isDispatchThread()
+ return self.attrs.get(ATTR_SERVICE_MANAGER_ID)
+
+ def getAgentID(self):
+ """@return agent unique ID, same as getAttributes().get(ATTR_AGENT_ID)"""
+ assert protocol.isDispatchThread()
+ return self.attrs.get(ATTR_AGENT_ID)
+
+ def getName(self):
+ """@return peer name, same as getAttributes().get(ATTR_NAME)"""
+ return self.attrs.get(ATTR_NAME)
+
+ def getOSName(self):
+ """@return agent OS name, same as getAttributes().get(ATTR_OS_NAME)"""
+ return self.attrs.get(ATTR_OS_NAME)
+
+ def getTransportName(self):
+ """@return transport name, same as getAttributes().get(ATTR_TRANSPORT_NAME)"""
+ return self.attrs.get(ATTR_TRANSPORT_NAME)
+
+ def openChannel(self):
+ """Open channel to communicate with this peer.
+ Note: the channel is not fully open yet when this method returns.
+ Its state is channel.STATE_OPENING.
+ Protocol.ChannelOpenListener and IChannel.IChannelListener listeners will be called when
+ the channel will change state to open or closed.
+ Clients are supposed to register IChannel.IChannelListener right after calling openChannel(), or,
+ at least, in same dispatch cycle. For example:
+ channel = peer.openChannel()
+ channel.addChannelListener(...)
+ """
+ raise RuntimeError("Abstract method")
+
+
+class TransientPeer(Peer):
+ """
+ Transient implementation of IPeer interface.
+ Objects of this class are not tracked by Locator service.
+ See AbstractPeer for IPeer objects that should go into the Locator table.
+ """
+ def __init__(self, attrs):
+ self.rw_attrs = {}
+ self.rw_attrs.update(attrs)
+ # TODO readonly map
+ ro_attrs = {}
+ ro_attrs.update(self.rw_attrs)
+ super(TransientPeer, self).__init__(ro_attrs)
+
+ def openChannel(self):
+ return transport.openChannel(self)
+
+class LocalPeer(TransientPeer):
+ """
+ LocalPeer object represents local end-point of TCF communication channel.
+ There should be exactly one such object in a TCF agent.
+ The object can be used to open a loop-back communication channel that allows
+ the agent to access its own services same way as remote services.
+ Note that "local" here is relative to the agent, and not same as in "local host".
+ """
+ def __init__(self):
+ super(LocalPeer, self).__init__(self.createAttributes())
+
+ def createAttributes(self):
+ attrs = {
+ ATTR_ID : "TCFLocal",
+ ATTR_SERVICE_MANAGER_ID : services.getServiceManagerID(),
+ ATTR_AGENT_ID : protocol.getAgentID(),
+ ATTR_NAME : "Local Peer",
+ ATTR_OS_NAME : os.name,
+ ATTR_TRANSPORT_NAME : "Loop"
+ }
+ return attrs;
+
+class AbstractPeer(TransientPeer):
+ """
+ Abstract implementation of IPeer interface.
+ Objects of this class are stored in Locator service peer table.
+ The class implements sending notification events to Locator listeners.
+ See TransientPeer for IPeer objects that are not stored in the Locator table.
+ """
+
+ last_heart_beat_time = 0
+
+ def __init__(self, attrs):
+ super(AbstractPeer, self).__init__(attrs)
+ assert protocol.isDispatchThread()
+ id = self.getID()
+ assert id
+ peers = protocol.getLocator().getPeers()
+ if isinstance(peers.get(id), RemotePeer):
+ peers.get(id).dispose()
+ assert id not in peers
+ peers[id] = self
+ self.sendPeerAddedEvent()
+
+ def dispose(self):
+ assert protocol.isDispatchThread()
+ id = self.getID()
+ assert id
+ peers = protocol.getLocator().getPeers()
+ assert peers.get(id) == self
+ del peers[id]
+ self.sendPeerRemovedEvent()
+
+ def onChannelTerminated(self):
+ # A channel to this peer was terminated:
+ # not delaying next heart beat helps client to recover much faster.
+ self.last_heart_beat_time = 0
+
+ def updateAttributes(self, attrs):
+ equ = True
+ assert attrs.get(ATTR_ID) == self.rw_attrs.get(ATTR_ID)
+ for key in self.rw_attrs.keys():
+ if self.rw_attrs.get(key) != attrs.get(key):
+ equ = False
+ break
+ for key in attrs.keys():
+ if attrs.get(key) != self.rw_attrs.get(key):
+ equ = False
+ break
+ timeVal = int(time.time() * 1000)
+ if not equ:
+ self.rw_attrs.clear()
+ self.rw_attrs.update(attrs)
+ for l in protocol.getLocator().getListeners():
+ try:
+ l.peerChanged(self)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ try:
+ args = [self.rw_attrs]
+ protocol.sendEvent(locator.NAME, "peerChanged", json.dumps(args))
+ except IOError as x:
+ protocol.log("Locator: failed to send 'peerChanged' event", x)
+ self.last_heart_beat_time = timeVal
+ elif self.last_heart_beat_time + locator.DATA_RETENTION_PERIOD / 4 < timeVal:
+ for l in protocol.getLocator().getListeners():
+ try:
+ l.peerHeartBeat(attrs.get(ATTR_ID))
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ try:
+ args = [self.rw_attrs.get(ATTR_ID)]
+ protocol.sendEvent(locator.NAME, "peerHeartBeat", json.dumps(args))
+ except IOError as x:
+ protocol.log("Locator: failed to send 'peerHeartBeat' event", x)
+ self.last_heart_beat_time = timeVal
+
+ def sendPeerAddedEvent(self):
+ for l in protocol.getLocator().getListeners():
+ try:
+ l.peerAdded(self)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ try:
+ args = [self.rw_attrs]
+ protocol.sendEvent(locator.NAME, "peerAdded", json.dumps(args))
+ except IOError as x:
+ protocol.log("Locator: failed to send 'peerAdded' event", x)
+ self.last_heart_beat_time = int(time.time() * 1000)
+
+ def sendPeerRemovedEvent(self):
+ for l in protocol.getLocator().getListeners():
+ try:
+ l.peerRemoved(self.rw_attrs.get(ATTR_ID))
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ try:
+ args = [self.rw_attrs.get(ATTR_ID)]
+ protocol.sendEvent(locator.NAME, "peerRemoved", json.dumps(args))
+ except IOError as x:
+ protocol.log("Locator: failed to send 'peerRemoved' event", x)
+
+
+class RemotePeer(AbstractPeer):
+ """
+ RemotePeer objects represent TCF agents that Locator service discovered on local network.
+ This includes both local host agents and remote host agents.
+ Note that "remote peer" means any peer accessible over network,
+ it does not imply the agent is running on a "remote host".
+ If an agent binds multiple network interfaces or multiple ports, it can be represented by
+ multiple RemotePeer objects - one per each network address/port combination.
+ RemotePeer objects life cycle is managed by Locator service.
+ """
+
+ last_update_time = 0
+
+ def __init__(self, attrs):
+ super(RemotePeer, self).__init__(attrs)
+ self.last_update_time = int(time.time() * 1000)
+
+ def updateAttributes(self, attrs):
+ super(RemotePeer, self).updateAttributes(attrs)
+ self.last_update_time = int(time.time() * 1000)
+
+ def getLastUpdateTime(self):
+ return self.last_update_time
diff --git a/python/src/tcf/services/__init__.py b/python/src/tcf/services/__init__.py
index 9cad2fa40..1432a02b0 100644
--- a/python/src/tcf/services/__init__.py
+++ b/python/src/tcf/services/__init__.py
@@ -1,127 +1,127 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import threading, collections
-from tcf import protocol
-
-_providers = []
-_lock = threading.RLock()
-
-class ServiceProvider(object):
- """
- Clients can implement this abstract class if they want to provide implementation of a local service or
- remote service proxy.
- """
- def getLocalService(self, channel):
- pass
- def getServiceProxy(self, channel, service_name):
- pass
-
-def addServiceProvider(provider):
- with _lock:
- _providers.append(provider)
-
-def removeServiceProvider(provider):
- with _lock:
- _providers.remove(provider)
-
-def onChannelCreated(channel, services_by_name):
- with _lock:
- # TODO ZeroCopy support is incomplete
-# zero_copy = ZeroCopy()
-# services_by_name[zero_copy.getName()] = zero_copy
- for provider in _providers:
- try:
- arr = provider.getLocalService(channel)
- if not arr: continue
- for service in arr:
- if service.getName() in services_by_name: continue
- services_by_name[service.getName()] = service
- except Exception as x:
- protocol.log("Error calling TCF service provider", x);
-
-def onChannelOpened(channel, service_names, services_by_name):
- with _lock:
- for name in service_names:
- for provider in _providers:
- try:
- service = provider.getServiceProxy(channel, name)
- if not service: continue
- services_by_name[name] = service
- break
- except Exception as x:
- protocol.log("Error calling TCF service provider", x)
- if name in services_by_name: continue
- services_by_name[name] = GenericProxy(channel, name)
-
-def getServiceManagerID():
- # In current implementation ServiceManager is a singleton,
- # so its ID is same as agent ID.
- return protocol.getAgentID()
-
-class GenericCallback(object):
- def __init__(self, callback):
- self.callback = callback
- def __getattr__(self, attr):
- if attr.startswith("done"):
- return self.callback
-
-class Service(object):
- def getName(self):
- raise NotImplementedError("Abstract method")
- def __str__(self):
- return self.getName()
- def _makeCallback(self, done):
- if isinstance(done, collections.Callable):
- return GenericCallback(done)
- return done
-
-class ZeroCopy(Service):
- def getName(self):
- return "ZeroCopy"
-
-class GenericProxy(Service):
- """
- * Objects of GenericProxy class represent remote services, which don't
- * have a proxy class defined for them.
- * Clients still can use such services, but framework will not provide
- * service specific utility methods for message formatting and parsing.
- """
- def __init__(self, channel, name):
- self.__channel = channel
- self.name = name
- def getName(self):
- return self.name
- def getChannel(self):
- return self.__channel
-
-class DefaultServiceProvider(ServiceProvider):
- package_base = "tcf.services.remote"
- def getLocalService(self, channel):
- # TODO DiagnosticsService
- #return [DiagnosticsService(channel)]
- return []
- def getServiceProxy(self, channel, service_name):
- service = None
- try:
- clsName = service_name + "Proxy"
- package = self.package_base + "." + clsName
- clsModule = __import__(package, fromlist=[clsName], globals=globals())
- cls = clsModule.__dict__.get(clsName)
- service = cls(channel)
- assert service_name == service.getName()
- except ImportError:
- pass
- except Exception as x:
- protocol.log("Cannot instantiate service proxy for "+service_name, x)
- return service
-
-addServiceProvider(DefaultServiceProvider())
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading, collections
+from tcf import protocol
+
+_providers = []
+_lock = threading.RLock()
+
+class ServiceProvider(object):
+ """
+ Clients can implement this abstract class if they want to provide implementation of a local service or
+ remote service proxy.
+ """
+ def getLocalService(self, channel):
+ pass
+ def getServiceProxy(self, channel, service_name):
+ pass
+
+def addServiceProvider(provider):
+ with _lock:
+ _providers.append(provider)
+
+def removeServiceProvider(provider):
+ with _lock:
+ _providers.remove(provider)
+
+def onChannelCreated(channel, services_by_name):
+ with _lock:
+ # TODO ZeroCopy support is incomplete
+# zero_copy = ZeroCopy()
+# services_by_name[zero_copy.getName()] = zero_copy
+ for provider in _providers:
+ try:
+ arr = provider.getLocalService(channel)
+ if not arr: continue
+ for service in arr:
+ if service.getName() in services_by_name: continue
+ services_by_name[service.getName()] = service
+ except Exception as x:
+ protocol.log("Error calling TCF service provider", x);
+
+def onChannelOpened(channel, service_names, services_by_name):
+ with _lock:
+ for name in service_names:
+ for provider in _providers:
+ try:
+ service = provider.getServiceProxy(channel, name)
+ if not service: continue
+ services_by_name[name] = service
+ break
+ except Exception as x:
+ protocol.log("Error calling TCF service provider", x)
+ if name in services_by_name: continue
+ services_by_name[name] = GenericProxy(channel, name)
+
+def getServiceManagerID():
+ # In current implementation ServiceManager is a singleton,
+ # so its ID is same as agent ID.
+ return protocol.getAgentID()
+
+class GenericCallback(object):
+ def __init__(self, callback):
+ self.callback = callback
+ def __getattr__(self, attr):
+ if attr.startswith("done"):
+ return self.callback
+
+class Service(object):
+ def getName(self):
+ raise NotImplementedError("Abstract method")
+ def __str__(self):
+ return self.getName()
+ def _makeCallback(self, done):
+ if isinstance(done, collections.Callable):
+ return GenericCallback(done)
+ return done
+
+class ZeroCopy(Service):
+ def getName(self):
+ return "ZeroCopy"
+
+class GenericProxy(Service):
+ """
+ * Objects of GenericProxy class represent remote services, which don't
+ * have a proxy class defined for them.
+ * Clients still can use such services, but framework will not provide
+ * service specific utility methods for message formatting and parsing.
+ """
+ def __init__(self, channel, name):
+ self.__channel = channel
+ self.name = name
+ def getName(self):
+ return self.name
+ def getChannel(self):
+ return self.__channel
+
+class DefaultServiceProvider(ServiceProvider):
+ package_base = "tcf.services.remote"
+ def getLocalService(self, channel):
+ # TODO DiagnosticsService
+ #return [DiagnosticsService(channel)]
+ return []
+ def getServiceProxy(self, channel, service_name):
+ service = None
+ try:
+ clsName = service_name + "Proxy"
+ package = self.package_base + "." + clsName
+ clsModule = __import__(package, fromlist=[clsName], globals=globals())
+ cls = clsModule.__dict__.get(clsName)
+ service = cls(channel)
+ assert service_name == service.getName()
+ except ImportError:
+ pass
+ except Exception as x:
+ protocol.log("Cannot instantiate service proxy for "+service_name, x)
+ return service
+
+addServiceProvider(DefaultServiceProvider())
diff --git a/python/src/tcf/services/breakpoints.py b/python/src/tcf/services/breakpoints.py
index 0ca646119..23a5d2d25 100644
--- a/python/src/tcf/services/breakpoints.py
+++ b/python/src/tcf/services/breakpoints.py
@@ -1,313 +1,313 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Breakpoint is represented by unique identifier and set of properties.
-Breakpoint identifier (String id) needs to be unique across all hosts and targets.
-
-Breakpoint properties (Map<String,Object>) is extendible collection of named attributes,
-which define breakpoint location and behavior. This module defines some common
-attribute names (see PROP_*), host tools and target agents may support additional attributes.
-
-For each breakpoint a target agent maintains another extendible collection of named attributes:
-breakpoint status (Map<String,Object>, see STATUS_*). While breakpoint properties are
-persistent and represent user input, breakpoint status reflects dynamic target agent reports
-about breakpoint current state, like actual addresses where breakpoint is planted or planting errors.
-"""
-
-from tcf import services
-
-# Service name.
-NAME = "Breakpoints"
-
-# Breakpoint property names.
-PROP_ID = "ID" # String
-PROP_ENABLED = "Enabled" # Boolean
-PROP_TYPE = "BreakpointType" # String
-PROP_CONTEXTNAMES = "ContextNames" # Array
-PROP_CONTEXTIDS = "ContextIds" # Array
-PROP_EXECUTABLEPATHS = "ExecPaths" # Array
-PROP_LOCATION = "Location" # String
-PROP_SIZE = "Size" # Number
-PROP_ACCESSMODE = "AccessMode" # Number
-PROP_FILE = "File" # String
-PROP_LINE = "Line" # Number
-PROP_COLUMN = "Column" # Number
-PROP_PATTERN = "MaskValue" # Number
-PROP_MASK = "Mask" # Number
-PROP_STOP_GROUP = "StopGroup" # Array
-PROP_IGNORECOUNT = "IgnoreCount" # Number
-PROP_TIME = "Time" # Number
-PROP_SCALE = "TimeScale" # String
-PROP_UNITS = "TimeUnits" # String
-PROP_CONDITION = "Condition" # String
-PROP_TEMPORARY = "Temporary" # Boolean
-
-# BreakpointType values
-TYPE_SOFTWARE = "Software",
-TYPE_HARDWARE = "Hardware"
-TYPE_AUTO = "Auto"
-
-# AccessMode values
-ACCESSMODE_READ = 0x01
-ACCESSMODE_WRITE = 0x02
-ACCESSMODE_EXECUTE = 0x04
-ACCESSMODE_CHANGE = 0x08
-
-# TimeScale values
-TIMESCALE_RELATIVE = "Relative"
-TIMESCALE_ABSOLUTE = "Absolute"
-
-# TimeUnits values
-TIMEUNIT_NSECS = "Nanoseconds"
-TIMEUNIT_CYCLE_COUNT = "CycleCount"
-TIMEUNIT_INSTRUCTION_COUNT = "InstructionCount"
-
-# Breakpoint status field names.
-STATUS_INSTANCES = "Instances" # Array of Map<String,Object>
-STATUS_ERROR= "Error" # String
-STATUS_FILE = "File" # String
-STATUS_LINE = "Line" # Number
-STATUS_COLUMN = "Column" # Number
-
-# Breakpoint instance field names.
-INSTANCE_ERROR = "Error" # String
-INSTANCE_CONTEXT = "LocationContext" # String
-INSTANCE_ADDRESS = "Address" # Number
-
-# Breakpoint service capabilities.
-CAPABILITY_CONTEXT_ID = "ID" # String
-CAPABILITY_HAS_CHILDREN = "HasChildren" # Boolean
-CAPABILITY_LOCATION = "Location" # Boolean
-CAPABILITY_CONDITION = "Condition" # Boolean
-CAPABILITY_FILE_LINE = "FileLine" # Boolean
-CAPABILITY_CONTEXTIDS = "ContextIds" # Boolean
-CAPABILITY_STOP_GROUP = "StopGroup" # Boolean
-CAPABILITY_IGNORECOUNT = "IgnoreCount" # Boolean
-CAPABILITY_ACCESSMODE = "AccessMode" # Number
-
-class BreakpointsService(services.Service):
- def getName(self):
- return NAME
-
- def set(self, properties, done):
- """
- Download breakpoints data to target agent.
- The command is intended to be used only to initialize target breakpoints table
- when communication channel is open. After that, host should
- notify target about (incremental) changes in breakpoint data by sending
- add, change and remove commands.
-
- @param properties - array of breakpoints.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def add(self, properties, done):
- """
- Called when breakpoint is added into breakpoints table.
- @param properties - breakpoint properties.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def change(self, properties, done):
- """
- Called when breakpoint properties are changed.
- @param properties - breakpoint properties.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def enable(self, ids, done):
- """
- Tell target to change (only) PROP_ENABLED breakpoint property to 'true'.
- @param ids - array of enabled breakpoint identifiers.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def disable(self, ids, done):
- """
- Tell target to change (only) PROP_ENABLED breakpoint property to 'false'.
- @param ids - array of disabled breakpoint identifiers.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def remove(self, ids, done):
- """
- Tell target to remove breakpoints.
- @param id - unique breakpoint identifier.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneCommand
- """
- raise NotImplementedError("Abstract method")
-
- def getIDs(self, done):
- """
- Upload IDs of breakpoints known to target agent.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneGetIDs
- """
- raise NotImplementedError("Abstract method")
-
- def getProperties(self, id, done):
- """
- Upload properties of given breakpoint from target agent breakpoint table.
- @param id - unique breakpoint identifier.
- @param done - command result call back object.
- @see DoneGetProperties
- """
- raise NotImplementedError("Abstract method")
-
- def getStatus(self, id, done):
- """
- Upload status of given breakpoint from target agent.
- @param id - unique breakpoint identifier.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneGetStatus
- """
- raise NotImplementedError("Abstract method")
-
- def getCapabilities(self, id, done):
- """
- Report breakpoint service capabilities to clients so they
- can adjust to different implementations of the service.
- When called with a None ("") context ID the global capabilities are returned,
- otherwise context specific capabilities are returned. A special capability
- property is used to indicate that all child contexts have the same
- capabilities.
- @param id - a context ID or None.
- @param done - command result call back object.
- @return - pending command handle.
- @see DoneGetCapabilities
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add breakpoints service event listener.
- @param listener - object that implements BreakpointsListener interface.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove breakpoints service event listener.
- @param listener - object that implements BreakpointsListener interface.
- """
- raise NotImplementedError("Abstract method")
-
-
-class DoneCommand(object):
- "Call back interface for breakpoint service commands."
- def doneCommand(self, token, error):
- """
- Called when command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneGetIDs(object):
- "Call back interface for 'getIDs' command."
- def doneGetIDs(self, token, error, ids):
- """
- Called when 'getIDs' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param ids - IDs of breakpoints known to target agent.
- """
- pass
-
-class DoneGetProperties(object):
- "Call back interface for 'getProperties' command."
- def doneGetProperties(self, token, error, properties):
- """
- Called when 'getProperties' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param properties - properties of the breakpoint.
- """
- pass
-
-class DoneGetStatus(object):
- "Call back interface for 'getStatus' command."
- def doneGetStatus(self, token, error, status):
- """
- Called when 'getStatus' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param status - status of the breakpoint.
- """
- pass
-
-class DoneGetCapabilities(object):
- "Call back interface for 'getCapabilities' command."
- def doneGetCapabilities(self, token, error, capabilities):
- """
- Called when 'getCapabilities' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param capabilities - breakpoints service capabilities description.
- """
- pass
-
-class BreakpointsListener(object):
- """
- Breakpoints service events listener.
- Note that contextAdded, contextChanged and contextRemoved events carry exactly same set
- of breakpoint properties that was sent by a client to a target. The purpose of these events is to
- let all clients know about breakpoints that were created by other clients.
- """
-
- def breakpointStatusChanged(self, id, status):
- """
- Called when breakpoint status changes.
- @param id - unique breakpoint identifier.
- @param status - breakpoint status.
- """
- pass
-
- def contextAdded(self, bps):
- """
- Called when a new breakpoints are added.
- @param bps - array of breakpoints.
- """
- pass
-
- def contextChanged(self, bps):
- """
- Called when breakpoint properties change.
- @param bps - array of breakpoints.
- """
- pass
-
- def contextRemoved(self, ids):
- """
- Called when breakpoints are removed .
- @param ids - array of breakpoint IDs.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Breakpoint is represented by unique identifier and set of properties.
+Breakpoint identifier (String id) needs to be unique across all hosts and targets.
+
+Breakpoint properties (Map<String,Object>) is extendible collection of named attributes,
+which define breakpoint location and behavior. This module defines some common
+attribute names (see PROP_*), host tools and target agents may support additional attributes.
+
+For each breakpoint a target agent maintains another extendible collection of named attributes:
+breakpoint status (Map<String,Object>, see STATUS_*). While breakpoint properties are
+persistent and represent user input, breakpoint status reflects dynamic target agent reports
+about breakpoint current state, like actual addresses where breakpoint is planted or planting errors.
+"""
+
+from tcf import services
+
+# Service name.
+NAME = "Breakpoints"
+
+# Breakpoint property names.
+PROP_ID = "ID" # String
+PROP_ENABLED = "Enabled" # Boolean
+PROP_TYPE = "BreakpointType" # String
+PROP_CONTEXTNAMES = "ContextNames" # Array
+PROP_CONTEXTIDS = "ContextIds" # Array
+PROP_EXECUTABLEPATHS = "ExecPaths" # Array
+PROP_LOCATION = "Location" # String
+PROP_SIZE = "Size" # Number
+PROP_ACCESSMODE = "AccessMode" # Number
+PROP_FILE = "File" # String
+PROP_LINE = "Line" # Number
+PROP_COLUMN = "Column" # Number
+PROP_PATTERN = "MaskValue" # Number
+PROP_MASK = "Mask" # Number
+PROP_STOP_GROUP = "StopGroup" # Array
+PROP_IGNORECOUNT = "IgnoreCount" # Number
+PROP_TIME = "Time" # Number
+PROP_SCALE = "TimeScale" # String
+PROP_UNITS = "TimeUnits" # String
+PROP_CONDITION = "Condition" # String
+PROP_TEMPORARY = "Temporary" # Boolean
+
+# BreakpointType values
+TYPE_SOFTWARE = "Software",
+TYPE_HARDWARE = "Hardware"
+TYPE_AUTO = "Auto"
+
+# AccessMode values
+ACCESSMODE_READ = 0x01
+ACCESSMODE_WRITE = 0x02
+ACCESSMODE_EXECUTE = 0x04
+ACCESSMODE_CHANGE = 0x08
+
+# TimeScale values
+TIMESCALE_RELATIVE = "Relative"
+TIMESCALE_ABSOLUTE = "Absolute"
+
+# TimeUnits values
+TIMEUNIT_NSECS = "Nanoseconds"
+TIMEUNIT_CYCLE_COUNT = "CycleCount"
+TIMEUNIT_INSTRUCTION_COUNT = "InstructionCount"
+
+# Breakpoint status field names.
+STATUS_INSTANCES = "Instances" # Array of Map<String,Object>
+STATUS_ERROR= "Error" # String
+STATUS_FILE = "File" # String
+STATUS_LINE = "Line" # Number
+STATUS_COLUMN = "Column" # Number
+
+# Breakpoint instance field names.
+INSTANCE_ERROR = "Error" # String
+INSTANCE_CONTEXT = "LocationContext" # String
+INSTANCE_ADDRESS = "Address" # Number
+
+# Breakpoint service capabilities.
+CAPABILITY_CONTEXT_ID = "ID" # String
+CAPABILITY_HAS_CHILDREN = "HasChildren" # Boolean
+CAPABILITY_LOCATION = "Location" # Boolean
+CAPABILITY_CONDITION = "Condition" # Boolean
+CAPABILITY_FILE_LINE = "FileLine" # Boolean
+CAPABILITY_CONTEXTIDS = "ContextIds" # Boolean
+CAPABILITY_STOP_GROUP = "StopGroup" # Boolean
+CAPABILITY_IGNORECOUNT = "IgnoreCount" # Boolean
+CAPABILITY_ACCESSMODE = "AccessMode" # Number
+
+class BreakpointsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def set(self, properties, done):
+ """
+ Download breakpoints data to target agent.
+ The command is intended to be used only to initialize target breakpoints table
+ when communication channel is open. After that, host should
+ notify target about (incremental) changes in breakpoint data by sending
+ add, change and remove commands.
+
+ @param properties - array of breakpoints.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def add(self, properties, done):
+ """
+ Called when breakpoint is added into breakpoints table.
+ @param properties - breakpoint properties.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def change(self, properties, done):
+ """
+ Called when breakpoint properties are changed.
+ @param properties - breakpoint properties.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def enable(self, ids, done):
+ """
+ Tell target to change (only) PROP_ENABLED breakpoint property to 'true'.
+ @param ids - array of enabled breakpoint identifiers.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def disable(self, ids, done):
+ """
+ Tell target to change (only) PROP_ENABLED breakpoint property to 'false'.
+ @param ids - array of disabled breakpoint identifiers.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def remove(self, ids, done):
+ """
+ Tell target to remove breakpoints.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneCommand
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getIDs(self, done):
+ """
+ Upload IDs of breakpoints known to target agent.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetIDs
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getProperties(self, id, done):
+ """
+ Upload properties of given breakpoint from target agent breakpoint table.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @see DoneGetProperties
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getStatus(self, id, done):
+ """
+ Upload status of given breakpoint from target agent.
+ @param id - unique breakpoint identifier.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetStatus
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getCapabilities(self, id, done):
+ """
+ Report breakpoint service capabilities to clients so they
+ can adjust to different implementations of the service.
+ When called with a None ("") context ID the global capabilities are returned,
+ otherwise context specific capabilities are returned. A special capability
+ property is used to indicate that all child contexts have the same
+ capabilities.
+ @param id - a context ID or None.
+ @param done - command result call back object.
+ @return - pending command handle.
+ @see DoneGetCapabilities
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add breakpoints service event listener.
+ @param listener - object that implements BreakpointsListener interface.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove breakpoints service event listener.
+ @param listener - object that implements BreakpointsListener interface.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class DoneCommand(object):
+ "Call back interface for breakpoint service commands."
+ def doneCommand(self, token, error):
+ """
+ Called when command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneGetIDs(object):
+ "Call back interface for 'getIDs' command."
+ def doneGetIDs(self, token, error, ids):
+ """
+ Called when 'getIDs' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param ids - IDs of breakpoints known to target agent.
+ """
+ pass
+
+class DoneGetProperties(object):
+ "Call back interface for 'getProperties' command."
+ def doneGetProperties(self, token, error, properties):
+ """
+ Called when 'getProperties' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param properties - properties of the breakpoint.
+ """
+ pass
+
+class DoneGetStatus(object):
+ "Call back interface for 'getStatus' command."
+ def doneGetStatus(self, token, error, status):
+ """
+ Called when 'getStatus' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param status - status of the breakpoint.
+ """
+ pass
+
+class DoneGetCapabilities(object):
+ "Call back interface for 'getCapabilities' command."
+ def doneGetCapabilities(self, token, error, capabilities):
+ """
+ Called when 'getCapabilities' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param capabilities - breakpoints service capabilities description.
+ """
+ pass
+
+class BreakpointsListener(object):
+ """
+ Breakpoints service events listener.
+ Note that contextAdded, contextChanged and contextRemoved events carry exactly same set
+ of breakpoint properties that was sent by a client to a target. The purpose of these events is to
+ let all clients know about breakpoints that were created by other clients.
+ """
+
+ def breakpointStatusChanged(self, id, status):
+ """
+ Called when breakpoint status changes.
+ @param id - unique breakpoint identifier.
+ @param status - breakpoint status.
+ """
+ pass
+
+ def contextAdded(self, bps):
+ """
+ Called when a new breakpoints are added.
+ @param bps - array of breakpoints.
+ """
+ pass
+
+ def contextChanged(self, bps):
+ """
+ Called when breakpoint properties change.
+ @param bps - array of breakpoints.
+ """
+ pass
+
+ def contextRemoved(self, ids):
+ """
+ Called when breakpoints are removed .
+ @param ids - array of breakpoint IDs.
+ """
+ pass
diff --git a/python/src/tcf/services/diagnostics.py b/python/src/tcf/services/diagnostics.py
index 54bfa2050..d16ae51df 100644
--- a/python/src/tcf/services/diagnostics.py
+++ b/python/src/tcf/services/diagnostics.py
@@ -1,285 +1,285 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-This is an optional service that can be implemented by a peer.
-If implemented, the service can be used for testing of the peer and
-communication channel functionality and reliability.
-"""
-
-from tcf import services
-
-NAME = "Diagnostics"
-
-class DiagnosticsService(services.Service):
- def getName(self):
- return NAME
-
- def echo(self, s, done):
- """
- 'echo' command result returns same string that was given as command argument.
- The command is used to test communication channel ability to transmit arbitrary strings in
- both directions.
- @param s - any string.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def echoFP(self, n, done):
- """
- 'echoFP' command result returns same floating point number that was given as command argument.
- The command is used to test communication channel ability to transmit arbitrary floating point numbers in
- both directions.
- @param n - any floating point number.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def echoERR(self, error, done):
- """
- 'echoERR' command result returns same error report that was given as command argument.
- The command is used to test remote agent ability to receive and transmit TCF error reports.
- @param error - an error object.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def getTestList(self, done):
- """
- Get list of test names that are implemented by the service.
- Clients can request remote peer to run a test from the list.
- When started, a test performs a predefined set actions.
- Nature of test actions is uniquely identified by test name.
- Exact description of test actions is a contract between client and remote peer,
- and it is not part of Diagnostics service specifications.
- Clients should not attempt to run a test if they don't recognize the test name.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def runTest(self, name, done):
- """
- Run a test. When started, a test performs a predefined set actions.
- Nature of test actions is uniquely identified by test name.
- Running test usually has associated execution context ID.
- Depending on the test, the ID can be used with services RunControl and/or Processes services to control
- test execution, and to obtain test results.
- @param name - test name
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def cancelTest(self, context_id, done):
- """
- Cancel execution of a test.
- @param context_id - text execution context ID.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def getSymbol(self, context_id, symbol_name, done):
- """
- Get information about a symbol in text execution context.
- @param context_id
- @param symbol_name
- @param done
- @return
- """
- return NotImplementedError("Abstract method")
-
- def createTestStreams(self, inp_buf_size, out_buf_size, done):
- """
- Create a pair of virtual streams, @see IStreams service.
- Remote ends of the streams are connected, so any data sent into 'inp' stream
- will become for available for reading from 'out' stream.
- The command is used for testing virtual streams.
- @param inp_buf_size - buffer size in bytes of the input stream.
- @param out_buf_size - buffer size in bytes of the output stream.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def disposeTestStream(self, id, done):
- """
- Dispose a virtual stream that was created by 'createTestStreams' command.
- @param id - the stream ID.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def not_implemented_command(self, done):
- """
- Send a command that is not implemented by peer.
- Used to test handling of 'N' messages by communication channel.
- @param done - command result call back object.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
-
-class DoneEcho(object):
- """
- Call back interface for 'echo' command.
- """
- def doneEcho(self, token, error, s):
- """
- Called when 'echo' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param s - same string as the command argument.
- """
- pass
-
-class DoneEchoFP(object):
- """
- Call back interface for 'echoFP' command.
- """
- def doneEchoFP(self, token, error, n):
- """
- Called when 'echoFP' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param n - same number as the command argument.
- """
- pass
-
-class DoneEchoERR(object):
- """
- Call back interface for 'echoERR' command.
- """
- def doneEchoERR(self, token, error, error_obj, error_msg):
- """
- Called when 'echoERR' command is done.
- @param token - command handle.
- @param error - communication error report or None.
- @param error_obj - error object, should be equal to the command argument.
- @param error_msg - error object converted to a human readable string.
- """
- pass
-
-class DoneGetTestList(object):
- """
- Call back interface for 'getTestList' command.
- """
- def doneGetTestList(self, token, error, list):
- """
- Called when 'getTestList' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param list - names of tests that are supported by the peer.
- """
- pass
-
-class DoneRunTest(object):
- """
- Call back interface for 'runTest' command.
- """
- def doneRunTest(self, token, error, context_id):
- """
- Called when 'runTest' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param context_id - test execution contest ID.
- """
- pass
-
-class DoneCancelTest(object):
- """
- Call back interface for 'cancelTest' command.
- """
- def doneCancelTest(self, token, error):
- """
- Called when 'cancelTest' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneGetSymbol(object):
- """
- Call back interface for 'getSymbol' command.
- """
- def doneGetSymbol(self, token, error, symbol):
- """
- Called when 'getSymbol' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param symbol
- """
- pass
-
-class Symbol(object):
- """
- Represents result value of 'getSymbol' command.
- """
- def __init__(self, props):
- self._props = props or {}
- def getSectionName(self):
- return self._props.get("Section")
- def getValue(self):
- return self._props.get("Value")
- def isUndef(self):
- val = self._props.get("Storage")
- return val == "UNDEF"
- def isCommon(self):
- val = self._props.get("Storage")
- return val == "COMMON"
- def isGlobal(self):
- val = self._props.get("Storage")
- return val == "GLOBAL"
- def isLocal(self):
- val = self._props.get("Storage")
- return val == "LOCAL"
- def isAbs(self):
- return self._props.get("Abs", False)
-
-class DoneCreateTestStreams(object):
- """
- Call back interface for 'createTestStreams' command.
- """
- def doneCreateTestStreams(self, token, error, inp_id, out_id):
- """
- Called when 'createTestStreams' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param inp_id - the input stream ID.
- @param out_id - the output stream ID.
- """
- pass
-
-class DoneDisposeTestStream(object):
- """
- Call back interface for 'disposeTestStream' command.
- """
- def doneDisposeTestStream(self, token, error):
- """
- Called when 'createTestStreams' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneNotImplementedCommand(object):
- def doneNotImplementedCommand(self, token, error):
- """
- Called when 'not_implemented_command' command is done.
- @param token - command handle.
- @param error - error object.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+This is an optional service that can be implemented by a peer.
+If implemented, the service can be used for testing of the peer and
+communication channel functionality and reliability.
+"""
+
+from tcf import services
+
+NAME = "Diagnostics"
+
+class DiagnosticsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def echo(self, s, done):
+ """
+ 'echo' command result returns same string that was given as command argument.
+ The command is used to test communication channel ability to transmit arbitrary strings in
+ both directions.
+ @param s - any string.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def echoFP(self, n, done):
+ """
+ 'echoFP' command result returns same floating point number that was given as command argument.
+ The command is used to test communication channel ability to transmit arbitrary floating point numbers in
+ both directions.
+ @param n - any floating point number.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def echoERR(self, error, done):
+ """
+ 'echoERR' command result returns same error report that was given as command argument.
+ The command is used to test remote agent ability to receive and transmit TCF error reports.
+ @param error - an error object.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def getTestList(self, done):
+ """
+ Get list of test names that are implemented by the service.
+ Clients can request remote peer to run a test from the list.
+ When started, a test performs a predefined set actions.
+ Nature of test actions is uniquely identified by test name.
+ Exact description of test actions is a contract between client and remote peer,
+ and it is not part of Diagnostics service specifications.
+ Clients should not attempt to run a test if they don't recognize the test name.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def runTest(self, name, done):
+ """
+ Run a test. When started, a test performs a predefined set actions.
+ Nature of test actions is uniquely identified by test name.
+ Running test usually has associated execution context ID.
+ Depending on the test, the ID can be used with services RunControl and/or Processes services to control
+ test execution, and to obtain test results.
+ @param name - test name
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def cancelTest(self, context_id, done):
+ """
+ Cancel execution of a test.
+ @param context_id - text execution context ID.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def getSymbol(self, context_id, symbol_name, done):
+ """
+ Get information about a symbol in text execution context.
+ @param context_id
+ @param symbol_name
+ @param done
+ @return
+ """
+ return NotImplementedError("Abstract method")
+
+ def createTestStreams(self, inp_buf_size, out_buf_size, done):
+ """
+ Create a pair of virtual streams, @see IStreams service.
+ Remote ends of the streams are connected, so any data sent into 'inp' stream
+ will become for available for reading from 'out' stream.
+ The command is used for testing virtual streams.
+ @param inp_buf_size - buffer size in bytes of the input stream.
+ @param out_buf_size - buffer size in bytes of the output stream.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def disposeTestStream(self, id, done):
+ """
+ Dispose a virtual stream that was created by 'createTestStreams' command.
+ @param id - the stream ID.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def not_implemented_command(self, done):
+ """
+ Send a command that is not implemented by peer.
+ Used to test handling of 'N' messages by communication channel.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+
+class DoneEcho(object):
+ """
+ Call back interface for 'echo' command.
+ """
+ def doneEcho(self, token, error, s):
+ """
+ Called when 'echo' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param s - same string as the command argument.
+ """
+ pass
+
+class DoneEchoFP(object):
+ """
+ Call back interface for 'echoFP' command.
+ """
+ def doneEchoFP(self, token, error, n):
+ """
+ Called when 'echoFP' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param n - same number as the command argument.
+ """
+ pass
+
+class DoneEchoERR(object):
+ """
+ Call back interface for 'echoERR' command.
+ """
+ def doneEchoERR(self, token, error, error_obj, error_msg):
+ """
+ Called when 'echoERR' command is done.
+ @param token - command handle.
+ @param error - communication error report or None.
+ @param error_obj - error object, should be equal to the command argument.
+ @param error_msg - error object converted to a human readable string.
+ """
+ pass
+
+class DoneGetTestList(object):
+ """
+ Call back interface for 'getTestList' command.
+ """
+ def doneGetTestList(self, token, error, list):
+ """
+ Called when 'getTestList' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param list - names of tests that are supported by the peer.
+ """
+ pass
+
+class DoneRunTest(object):
+ """
+ Call back interface for 'runTest' command.
+ """
+ def doneRunTest(self, token, error, context_id):
+ """
+ Called when 'runTest' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param context_id - test execution contest ID.
+ """
+ pass
+
+class DoneCancelTest(object):
+ """
+ Call back interface for 'cancelTest' command.
+ """
+ def doneCancelTest(self, token, error):
+ """
+ Called when 'cancelTest' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneGetSymbol(object):
+ """
+ Call back interface for 'getSymbol' command.
+ """
+ def doneGetSymbol(self, token, error, symbol):
+ """
+ Called when 'getSymbol' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param symbol
+ """
+ pass
+
+class Symbol(object):
+ """
+ Represents result value of 'getSymbol' command.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+ def getSectionName(self):
+ return self._props.get("Section")
+ def getValue(self):
+ return self._props.get("Value")
+ def isUndef(self):
+ val = self._props.get("Storage")
+ return val == "UNDEF"
+ def isCommon(self):
+ val = self._props.get("Storage")
+ return val == "COMMON"
+ def isGlobal(self):
+ val = self._props.get("Storage")
+ return val == "GLOBAL"
+ def isLocal(self):
+ val = self._props.get("Storage")
+ return val == "LOCAL"
+ def isAbs(self):
+ return self._props.get("Abs", False)
+
+class DoneCreateTestStreams(object):
+ """
+ Call back interface for 'createTestStreams' command.
+ """
+ def doneCreateTestStreams(self, token, error, inp_id, out_id):
+ """
+ Called when 'createTestStreams' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param inp_id - the input stream ID.
+ @param out_id - the output stream ID.
+ """
+ pass
+
+class DoneDisposeTestStream(object):
+ """
+ Call back interface for 'disposeTestStream' command.
+ """
+ def doneDisposeTestStream(self, token, error):
+ """
+ Called when 'createTestStreams' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneNotImplementedCommand(object):
+ def doneNotImplementedCommand(self, token, error):
+ """
+ Called when 'not_implemented_command' command is done.
+ @param token - command handle.
+ @param error - error object.
+ """
+ pass
diff --git a/python/src/tcf/services/disassembly.py b/python/src/tcf/services/disassembly.py
index 18abad1ae..f5260c3b5 100644
--- a/python/src/tcf/services/disassembly.py
+++ b/python/src/tcf/services/disassembly.py
@@ -1,131 +1,131 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-TCF Disassembly service interface.
-"""
-
-from tcf import services
-
-NAME = "Disassembly"
-
-# The name of the instruction set architecture, String
-CAPABILITY_ISA = "ISA"
-
-# If true, simplified mnemonics are supported or requested, Boolean
-CAPABILITY_SIMPLIFIED = "Simplified"
-
-# If true, pseudo-instructions are supported or requested, Boolean
-CAPABILITY_PSEUDO = "Pseudo"
-
-
-# Instruction field properties
-# The type of the instruction field. See FTYPE_*, String.
-FIELD_TYPE = "Type"
-
-# Value of the field for "String" and "Register" types, String.
-FIELD_TEXT = "Text"
-
-# Value of the field for "Address," "Displacement," or "Immediate" types, Number.
-FIELD_VALUE = "Value"
-
-# Context ID of the address space used with "Address" types, String.
-FIELD_ADDRESS_SPACE = "AddressSpace"
-
-# Instruction field types
-FTYPE_STRING = "String"
-FTYPE_Register = "Register"
-FTYPE_ADDRESS = "Address"
-FTYPE_DISPLACEMENT = "Displacement"
-FTYPE_IMMEDIATE = "Immediate"
-
-
-class DisassemblyService(services.Service):
- def getName(self):
- return NAME
-
- def getCapabilities(self, context_id, done):
- """
- Retrieve disassembly service capabilities a given context-id.
- @param context_id - a context ID, usually one returned by Run Control or Memory services.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def disassemble(self, context_id, addr, size, params, done):
- """
- Disassemble instruction code from a specified range of memory addresses, in a specified context.
- @param context_id - a context ID, usually one returned by Run Control or Memory services.
- @param addr - address of first instruction to disassemble.
- @param size - size in bytes of the address range.
- @param params - properties to control the disassembly output, an element of capabilities array, see getCapabilities.
- @param done - command result call back object.
- @return - pending command handle.
- """
-
-
-class DoneGetCapabilities(object):
- """
- Call back interface for 'getCapabilities' command.
- """
- def doneGetCapabilities(self, token, error, capabilities):
- """
- Called when capabilities retrieval is done.
- @param token - command handle.
- @param error - error object or None.
- @param capabilities - array of capabilities, see CAPABILITY_* for contents of each array element.
- """
- pass
-
-class DoneDisassemble(object):
- """
- Call back interface for 'disassemble' command.
- """
- def doneDisassemble(self, token, error, disassembly):
- """
- Called when disassembling is done.
- @param token - command handle.
- @param error - error object or None.
- @param disassembly - array of disassembly lines.
- """
- pass
-
-class DisassemblyLine(object):
- """
- Represents a single disassembly line.
- """
- def __init__(self, addr, size, instruction):
- self.addr = addr
- self.size = size or 0
- self.instruction = instruction
-
- def getAddress(self):
- """
- @return instruction address.
- """
- return self.addr
-
- def getSize(self):
- """
- @return instruction size in bytes.
- """
- return self.size
-
- def getInstruction(self):
- """
- @return array of instruction fields, each field is a collection of field properties, see FIELD_*.
- """
- return self.instruction
-
- def __str__(self):
- instr = "".join(map(str, self.instruction))
- return "[%s %s %s]" % (self.addr, self.size, instr)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+TCF Disassembly service interface.
+"""
+
+from tcf import services
+
+NAME = "Disassembly"
+
+# The name of the instruction set architecture, String
+CAPABILITY_ISA = "ISA"
+
+# If true, simplified mnemonics are supported or requested, Boolean
+CAPABILITY_SIMPLIFIED = "Simplified"
+
+# If true, pseudo-instructions are supported or requested, Boolean
+CAPABILITY_PSEUDO = "Pseudo"
+
+
+# Instruction field properties
+# The type of the instruction field. See FTYPE_*, String.
+FIELD_TYPE = "Type"
+
+# Value of the field for "String" and "Register" types, String.
+FIELD_TEXT = "Text"
+
+# Value of the field for "Address," "Displacement," or "Immediate" types, Number.
+FIELD_VALUE = "Value"
+
+# Context ID of the address space used with "Address" types, String.
+FIELD_ADDRESS_SPACE = "AddressSpace"
+
+# Instruction field types
+FTYPE_STRING = "String"
+FTYPE_Register = "Register"
+FTYPE_ADDRESS = "Address"
+FTYPE_DISPLACEMENT = "Displacement"
+FTYPE_IMMEDIATE = "Immediate"
+
+
+class DisassemblyService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getCapabilities(self, context_id, done):
+ """
+ Retrieve disassembly service capabilities a given context-id.
+ @param context_id - a context ID, usually one returned by Run Control or Memory services.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def disassemble(self, context_id, addr, size, params, done):
+ """
+ Disassemble instruction code from a specified range of memory addresses, in a specified context.
+ @param context_id - a context ID, usually one returned by Run Control or Memory services.
+ @param addr - address of first instruction to disassemble.
+ @param size - size in bytes of the address range.
+ @param params - properties to control the disassembly output, an element of capabilities array, see getCapabilities.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+
+
+class DoneGetCapabilities(object):
+ """
+ Call back interface for 'getCapabilities' command.
+ """
+ def doneGetCapabilities(self, token, error, capabilities):
+ """
+ Called when capabilities retrieval is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param capabilities - array of capabilities, see CAPABILITY_* for contents of each array element.
+ """
+ pass
+
+class DoneDisassemble(object):
+ """
+ Call back interface for 'disassemble' command.
+ """
+ def doneDisassemble(self, token, error, disassembly):
+ """
+ Called when disassembling is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param disassembly - array of disassembly lines.
+ """
+ pass
+
+class DisassemblyLine(object):
+ """
+ Represents a single disassembly line.
+ """
+ def __init__(self, addr, size, instruction):
+ self.addr = addr
+ self.size = size or 0
+ self.instruction = instruction
+
+ def getAddress(self):
+ """
+ @return instruction address.
+ """
+ return self.addr
+
+ def getSize(self):
+ """
+ @return instruction size in bytes.
+ """
+ return self.size
+
+ def getInstruction(self):
+ """
+ @return array of instruction fields, each field is a collection of field properties, see FIELD_*.
+ """
+ return self.instruction
+
+ def __str__(self):
+ instr = "".join(map(str, self.instruction))
+ return "[%s %s %s]" % (self.addr, self.size, instr)
diff --git a/python/src/tcf/services/expressions.py b/python/src/tcf/services/expressions.py
index 8da3b61e6..5b32a1c30 100644
--- a/python/src/tcf/services/expressions.py
+++ b/python/src/tcf/services/expressions.py
@@ -1,356 +1,356 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Expressions service allows TCF client to perform expression evaluation on remote target.
-The service can be used to retrieve or modify values of variables or any data structures in remote target memory.
-"""
-
-from tcf import services
-
-# Service name.
-NAME = "Expressions"
-
-class Expression(object):
- """
- Expression object represent an expression that can be evaluated by remote target.
- It has a unique ID and contains all information necessary to compute a value.
- The object data usually includes:
- 1. process, thread or stack frame ID that should be used to resolve symbol names
- 2. a script that can compute a value, like "x.y + z"
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Expression Context %s]" % self._props
-
- def getID(self):
- """
- Get context ID.
- @return context ID.
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Get parent context ID.
- @return parent context ID.
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getLanguage(self):
- """
- Get expression script language ID.
- @return language ID.
- """
- return self._props.get(PROP_LANGUAGE)
-
- def getExpression(self):
- """
- Return expression string - the script part of the context.
- @return expression script string
- """
- return self._props.get(PROP_EXPRESSION)
-
- def getSymbolID(self):
- """
- Return symbol ID if the expression represents a symbol (e.g. local variable).
- @return symbol ID
- """
- return self._props.get(PROP_SYMBOL_ID)
-
- def getBits(self):
- """
- Get size of expression value in bits.
- Can be 0 if value size is even number of bytes, use getSize() in such case.
- @return size in bits.
- """
- return self._props.get(PROP_BITS, 0)
-
- def getSize(self):
- """
- Get size in bytes. The size can include extra (unused) bits.
- This is "static" or "declared" size - as determined by expression type.
- @return size in bytes.
- """
- return self._props.get(PROP_SIZE, 0)
-
- def getTypeID(self):
- """
- Get expression type ID. Symbols service can be used to get type properties.
- This is "static" or "declared" type ID, actual type of a value can be different -
- if expression language supports dynamic typing.
- @return type ID.
- """
- return self._props.get(PROP_TYPE)
-
- def canAssign(self):
- """
- Check if the expression can be assigned a new value.
- @return true if can assign.
- """
- return self._props.get(PROP_CAN_ASSIGN)
-
- def getProperties(self):
- """
- Get complete map of context properties.
- @return map of context properties.
- """
- return self._props
-
-# Expression context property names.
-PROP_ID = "ID"
-PROP_PARENT_ID = "ParentID"
-PROP_SYMBOL_ID = "SymbolID"
-PROP_LANGUAGE = "Language"
-PROP_EXPRESSION = "Expression"
-PROP_BITS = "Bits"
-PROP_SIZE = "Size"
-PROP_TYPE = "Type"
-PROP_CAN_ASSIGN = "CanAssign"
-
-class Value(object):
- """
- Value represents result of expression evaluation.
- Note that same expression can be evaluated multiple times with different results.
- """
- def __init__(self, value, props):
- self._value = value
- self._props = props or {}
-
- def __str__(self):
- return "[Expression Value %s %s]" % (self._value, self._props)
-
- def getTypeClass(self):
- """
- Get value type class.
- @see symbols.TypeClass
- @return type class
- """
- return self._props.get(VAL_CLASS, 0)
-
- def getTypeID(self):
- """
- Get value type ID. Symbols service can be used to get type properties.
- @return type ID.
- """
- return self._props.get(VAL_TYPE)
-
- def isBigEndian(self):
- """
- Check endianness of the values.
- Big-endian means decreasing numeric significance with increasing byte number.
- @return true if big-endian.
- """
- return self._props.get(VAL_BIG_ENDIAN)
-
- def getValue(self):
- """
- Get value as array of bytes.
- @return value as array of bytes.
- """
- return self._value
-
- def getProperties(self):
- """
- Get complete map of value properties.
- @return map of value properties.
- """
- return self._props
-
-# Expression value property names.
-VAL_CLASS = "Class"
-VAL_TYPE = "Type"
-VAL_BIG_ENDIAN = "BigEndian"
-
-class ExpressionsService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve expression context info for given context ID.
- @see Expression
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve children IDs for given parent ID.
- Meaning of the operation depends on parent kind:
- 1. expression with type of a struct, union, or class - fields
- 2. expression with type of an enumeration - enumerators
- 3. expression with type of an array - array elements
- 4. stack frame - function arguments and local variables
- 5. thread - top stack frame function arguments and local variables
- 6. process - global variables
-
- Children list *does not* include IDs of expressions that were created by clients
- using "create" command.
-
- @param parent_context_id - parent context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def create(self, parent_id, language, expression, done):
- """
- Create an expression context.
- The context should be disposed after use.
- @param parent_id - a context ID that can be used to resolve symbol names.
- @param language - language of expression script, None means default language
- @param expression - expression script
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def dispose(self, id, done):
- """
- Dispose an expression context that was created by create()
- @param id - the expression context ID
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def evaluate(self, id, done):
- """
- Evaluate value of an expression context.
- @param id - the expression context ID
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def assign(self, id, value, done):
- """
- Assign a value to memory location determined by an expression.
- @param id - expression ID.
- @param value - value as an array of bytes.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add expressions service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove expressions service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context - context properties.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-
-class DoneCreate(object):
- """
- Client call back interface for create().
- """
- def doneCreate(self, token, error, context):
- """
- Called when context create context command is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context - context properties.
- """
- pass
-
-class DoneDispose(object):
- """
- Client call back interface for dispose().
- """
- def doneDispose(self, token, error):
- """
- Called when context dispose command is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- """
- pass
-
-class DoneEvaluate(object):
- """
- Client call back interface for evaluate().
- """
- def doneEvaluate(self, token, error, value):
- """
- Called when context dispose command is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param value - expression evaluation result
- """
- pass
-
-class DoneAssign(object):
- """
- Client call back interface for assign().
- """
- def doneAssign(self, token, error):
- """
- Called when assign command is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- """
- pass
-
-class ExpressionsListener(object):
- """
- Registers event listener is notified when registers context hierarchy
- changes, and when a register is modified by the service commands.
- """
- def valueChanged(self, id):
- """
- Called when expression value was changed and clients
- need to update themselves. Clients, at least, should invalidate
- corresponding cached expression data.
- Not every change is notified - it is not possible,
- only those, which are not caused by normal execution of the debuggee.
- At least, changes caused by "assign" command should be notified.
- @param id - expression context ID.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Expressions service allows TCF client to perform expression evaluation on remote target.
+The service can be used to retrieve or modify values of variables or any data structures in remote target memory.
+"""
+
+from tcf import services
+
+# Service name.
+NAME = "Expressions"
+
+class Expression(object):
+ """
+ Expression object represent an expression that can be evaluated by remote target.
+ It has a unique ID and contains all information necessary to compute a value.
+ The object data usually includes:
+ 1. process, thread or stack frame ID that should be used to resolve symbol names
+ 2. a script that can compute a value, like "x.y + z"
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Expression Context %s]" % self._props
+
+ def getID(self):
+ """
+ Get context ID.
+ @return context ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ @return parent context ID.
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getLanguage(self):
+ """
+ Get expression script language ID.
+ @return language ID.
+ """
+ return self._props.get(PROP_LANGUAGE)
+
+ def getExpression(self):
+ """
+ Return expression string - the script part of the context.
+ @return expression script string
+ """
+ return self._props.get(PROP_EXPRESSION)
+
+ def getSymbolID(self):
+ """
+ Return symbol ID if the expression represents a symbol (e.g. local variable).
+ @return symbol ID
+ """
+ return self._props.get(PROP_SYMBOL_ID)
+
+ def getBits(self):
+ """
+ Get size of expression value in bits.
+ Can be 0 if value size is even number of bytes, use getSize() in such case.
+ @return size in bits.
+ """
+ return self._props.get(PROP_BITS, 0)
+
+ def getSize(self):
+ """
+ Get size in bytes. The size can include extra (unused) bits.
+ This is "static" or "declared" size - as determined by expression type.
+ @return size in bytes.
+ """
+ return self._props.get(PROP_SIZE, 0)
+
+ def getTypeID(self):
+ """
+ Get expression type ID. Symbols service can be used to get type properties.
+ This is "static" or "declared" type ID, actual type of a value can be different -
+ if expression language supports dynamic typing.
+ @return type ID.
+ """
+ return self._props.get(PROP_TYPE)
+
+ def canAssign(self):
+ """
+ Check if the expression can be assigned a new value.
+ @return true if can assign.
+ """
+ return self._props.get(PROP_CAN_ASSIGN)
+
+ def getProperties(self):
+ """
+ Get complete map of context properties.
+ @return map of context properties.
+ """
+ return self._props
+
+# Expression context property names.
+PROP_ID = "ID"
+PROP_PARENT_ID = "ParentID"
+PROP_SYMBOL_ID = "SymbolID"
+PROP_LANGUAGE = "Language"
+PROP_EXPRESSION = "Expression"
+PROP_BITS = "Bits"
+PROP_SIZE = "Size"
+PROP_TYPE = "Type"
+PROP_CAN_ASSIGN = "CanAssign"
+
+class Value(object):
+ """
+ Value represents result of expression evaluation.
+ Note that same expression can be evaluated multiple times with different results.
+ """
+ def __init__(self, value, props):
+ self._value = value
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Expression Value %s %s]" % (self._value, self._props)
+
+ def getTypeClass(self):
+ """
+ Get value type class.
+ @see symbols.TypeClass
+ @return type class
+ """
+ return self._props.get(VAL_CLASS, 0)
+
+ def getTypeID(self):
+ """
+ Get value type ID. Symbols service can be used to get type properties.
+ @return type ID.
+ """
+ return self._props.get(VAL_TYPE)
+
+ def isBigEndian(self):
+ """
+ Check endianness of the values.
+ Big-endian means decreasing numeric significance with increasing byte number.
+ @return true if big-endian.
+ """
+ return self._props.get(VAL_BIG_ENDIAN)
+
+ def getValue(self):
+ """
+ Get value as array of bytes.
+ @return value as array of bytes.
+ """
+ return self._value
+
+ def getProperties(self):
+ """
+ Get complete map of value properties.
+ @return map of value properties.
+ """
+ return self._props
+
+# Expression value property names.
+VAL_CLASS = "Class"
+VAL_TYPE = "Type"
+VAL_BIG_ENDIAN = "BigEndian"
+
+class ExpressionsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve expression context info for given context ID.
+ @see Expression
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children IDs for given parent ID.
+ Meaning of the operation depends on parent kind:
+ 1. expression with type of a struct, union, or class - fields
+ 2. expression with type of an enumeration - enumerators
+ 3. expression with type of an array - array elements
+ 4. stack frame - function arguments and local variables
+ 5. thread - top stack frame function arguments and local variables
+ 6. process - global variables
+
+ Children list *does not* include IDs of expressions that were created by clients
+ using "create" command.
+
+ @param parent_context_id - parent context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def create(self, parent_id, language, expression, done):
+ """
+ Create an expression context.
+ The context should be disposed after use.
+ @param parent_id - a context ID that can be used to resolve symbol names.
+ @param language - language of expression script, None means default language
+ @param expression - expression script
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def dispose(self, id, done):
+ """
+ Dispose an expression context that was created by create()
+ @param id - the expression context ID
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def evaluate(self, id, done):
+ """
+ Evaluate value of an expression context.
+ @param id - the expression context ID
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def assign(self, id, value, done):
+ """
+ Assign a value to memory location determined by an expression.
+ @param id - expression ID.
+ @param value - value as an array of bytes.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add expressions service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove expressions service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context properties.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+
+class DoneCreate(object):
+ """
+ Client call back interface for create().
+ """
+ def doneCreate(self, token, error, context):
+ """
+ Called when context create context command is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context properties.
+ """
+ pass
+
+class DoneDispose(object):
+ """
+ Client call back interface for dispose().
+ """
+ def doneDispose(self, token, error):
+ """
+ Called when context dispose command is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ """
+ pass
+
+class DoneEvaluate(object):
+ """
+ Client call back interface for evaluate().
+ """
+ def doneEvaluate(self, token, error, value):
+ """
+ Called when context dispose command is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param value - expression evaluation result
+ """
+ pass
+
+class DoneAssign(object):
+ """
+ Client call back interface for assign().
+ """
+ def doneAssign(self, token, error):
+ """
+ Called when assign command is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ """
+ pass
+
+class ExpressionsListener(object):
+ """
+ Registers event listener is notified when registers context hierarchy
+ changes, and when a register is modified by the service commands.
+ """
+ def valueChanged(self, id):
+ """
+ Called when expression value was changed and clients
+ need to update themselves. Clients, at least, should invalidate
+ corresponding cached expression data.
+ Not every change is notified - it is not possible,
+ only those, which are not caused by normal execution of the debuggee.
+ At least, changes caused by "assign" command should be notified.
+ @param id - expression context ID.
+ """
+ pass
diff --git a/python/src/tcf/services/filesystem.py b/python/src/tcf/services/filesystem.py
index 524bea907..726b71810 100644
--- a/python/src/tcf/services/filesystem.py
+++ b/python/src/tcf/services/filesystem.py
@@ -1,603 +1,603 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-File System service provides file transfer (and more generally file
-system access) functionality in TCF. The service design is
-derived from SSH File Transfer Protocol specifications.
-
- Request Synchronization and Reordering
-
-The protocol and implementations MUST process requests relating to
-the same file in the order in which they are received. In other
-words, if an application submits multiple requests to the server, the
-results in the responses will be the same as if it had sent the
-requests one at a time and waited for the response in each case. For
-example, the server may process non-overlapping read/write requests
-to the same file in parallel, but overlapping reads and writes cannot
-be reordered or parallelized. However, there are no ordering
-restrictions on the server for processing requests from two different
-file transfer connections. The server may interleave and parallelize
-them at will.
-
-There are no restrictions on the order in which responses to
-outstanding requests are delivered to the client, except that the
-server must ensure fairness in the sense that processing of no
-request will be indefinitely delayed even if the client is sending
-other requests so that there are multiple outstanding requests all
-the time.
-
-There is no limit on the number of outstanding (non-acknowledged)
-requests that the client may send to the server. In practice this is
-limited by the buffering available on the data stream and the queuing
-performed by the server. If the server's queues are full, it should
-not read any more data from the stream, and flow control will prevent
-the client from sending more requests.
-
- File Names
-
-This protocol represents file names as strings. File names are
-assumed to use the slash ('/') character as a directory separator.
-
-File names starting with a slash are "absolute", and are relative to
-the root of the file system. Names starting with any other character
-are relative to the user's default directory (home directory). Client
-can use 'user()' command to retrieve current user home directory.
-
-Servers SHOULD interpret a path name component ".." as referring to
-the parent directory, and "." as referring to the current directory.
-If the server implementation limits access to certain parts of the
-file system, it must be extra careful in parsing file names when
-enforcing such restrictions. There have been numerous reported
-security bugs where a ".." in a path name has allowed access outside
-the intended area.
-
-An empty path name is valid, and it refers to the user's default
-directory (usually the user's home directory).
-
-Otherwise, no syntax is defined for file names by this specification.
-Clients should not make any other assumptions however, they can
-splice path name components returned by readdir() together
-using a slash ('/') as the separator, and that will work as expected.
-"""
-
-from tcf import services
-
-# Service name.
-NAME = "FileSystem"
-
-# Flags to be used with open() method.
-
-# Open the file for reading.
-TCF_O_READ = 0x00000001
-
-# Open the file for writing. If both this and TCF_O_READ are
-# specified, the file is opened for both reading and writing.
-TCF_O_WRITE = 0x00000002
-
-# Force all writes to append data at the end of the file.
-TCF_O_APPEND = 0x00000004
-
-# If this flag is specified, then a new file will be created if one
-# does not already exist (if TCF_O_TRUNC is specified, the new file will
-# be truncated to zero length if it previously exists).
-TCF_O_CREAT = 0x00000008
-
-# Forces an existing file with the same name to be truncated to zero
-# length when creating a file by specifying TCF_O_CREAT.
-# TCF_O_CREAT MUST also be specified if this flag is used.
-TCF_O_TRUNC = 0x00000010
-
-# Causes the request to fail if the named file already exists.
-# TCF_O_CREAT MUST also be specified if this flag is used.
-TCF_O_EXCL = 0x00000020
-
-# Flags to be used together with FileAttrs.
-# The flags specify which of the fields are present. Those fields
-# for which the corresponding flag is not set are not present (not
-# included in the message).
-ATTR_SIZE = 0x00000001
-ATTR_UIDGID = 0x00000002
-ATTR_PERMISSIONS = 0x00000004
-ATTR_ACMODTIME = 0x00000008
-
-class FileAttrs(object):
- """
- FileAttrs is used both when returning file attributes from
- the server and when sending file attributes to the server. When
- sending it to the server, the flags field specifies which attributes
- are included, and the server will use default values for the
- remaining attributes (or will not modify the values of remaining
- attributes). When receiving attributes from the server, the flags
- specify which attributes are included in the returned data. The
- server normally returns all attributes it knows about.
-
- Fields:
- The 'flags' specify which of the fields are present.
- The 'size' field specifies the size of the file in bytes.
- The 'uid' and 'gid' fields contain numeric Unix-like user and group
- identifiers, respectively.
- The 'permissions' field contains a bit mask of file permissions as
- defined by posix [1].
- The 'atime' and 'mtime' contain the access and modification times of
- the files, respectively. They are represented as milliseconds from
- midnight Jan 1, 1970 in UTC.
- attributes - Additional (non-standard) attributes.
- """
- def __init__(self, flags, size, uid, gid, permissions, atime, mtime, attributes):
- self.flags = flags
- self.size = size
- self.uid = uid
- self.gid = gid
- self.permissions = permissions
- self.atime = atime
- self.mtime = mtime
- self.attributes = attributes
-
- def isFile(self):
- """
- Determines if the file system object is a file on the remote file system.
-
- @return True if and only if the object on the remote system can be considered to have "contents" that
- have the potential to be read and written as a byte stream.
- """
- if (self.flags & ATTR_PERMISSIONS) == 0: return False
- return (self.permissions & S_IFMT) == S_IFREG
-
- def isDirectory(self):
- """
- Determines if the file system object is a directory on the remote file system.
-
- @return True if and only if the object on the remote system is a directory.
- That is, it contains entries that can be interpreted as other files.
- """
- if (self.flags & ATTR_PERMISSIONS) == 0: return False
- return (self.permissions & S_IFMT) == S_IFDIR
-
-# The following flags are defined for the 'permissions' field:
-S_IFMT = 0170000 # bitmask for the file type bitfields
-S_IFSOCK = 0140000 # socket
-S_IFLNK = 0120000 # symbolic link
-S_IFREG = 0100000 # regular file
-S_IFBLK = 0060000 # block device
-S_IFDIR = 0040000 # directory
-S_IFCHR = 0020000 # character device
-S_IFIFO = 0010000 # fifo
-S_ISUID = 0004000 # set UID bit
-S_ISGID = 0002000 # set GID bit (see below)
-S_ISVTX = 0001000 # sticky bit (see below)
-S_IRWXU = 00700 # mask for file owner permissions
-S_IRUSR = 00400 # owner has read permission
-S_IWUSR = 00200 # owner has write permission
-S_IXUSR = 00100 # owner has execute permission
-S_IRWXG = 00070 # mask for group permissions
-S_IRGRP = 00040 # group has read permission
-S_IWGRP = 00020 # group has write permission
-S_IXGRP = 00010 # group has execute permission
-S_IRWXO = 00007 # mask for permissions for others (not in group)
-S_IROTH = 00004 # others have read permission
-S_IWOTH = 00002 # others have write permission
-S_IXOTH = 00001 # others have execute permission
-
-class DirEntry(object):
- """
- Directory entry.
- Fields:
- 'filename' is a file name being returned. It is a relative name within
- the directory, without any path components
- 'longname' is an expanded format for the file name, similar to what
- is returned by "ls -l" on Unix systems.
- The format of the 'longname' field is unspecified by this protocol.
- It MUST be suitable for use in the output of a directory listing
- command (in fact, the recommended operation for a directory listing
- command is to simply display this data). However, clients SHOULD NOT
- attempt to parse the longname field for file attributes they SHOULD
- use the attrs field instead.
- 'attrs' is the attributes of the file.
- """
- def __init__(self, filename, longname, attrs):
- self.filename = filename
- self.longname = longname
- self.attrs = attrs
-
-class FileHandle(object):
- def __init__(self, service, id):
- self.service = service
- self.id = id
-
- def getService(self):
- return self.service
-
- def __str__(self):
- return "[File Handle '%s'" % self.id
-
-# Service specific error codes.
-
-# Indicates end-of-file condition for read() it means that no
-# more data is available in the file, and for readdir() it
-# indicates that no more files are contained in the directory.
-STATUS_EOF = 0x10001
-
-# This code is returned when a reference is made to a file which
-# should exist but doesn't.
-STATUS_NO_SUCH_FILE = 0x10002
-
-# is returned when the authenticated user does not have sufficient
-# permissions to perform the operation.
-STATUS_PERMISSION_DENIED = 0x10003
-
-class FileSystemException(IOError):
- """
- The class to represent File System error reports.
- """
- def __init__(self, message_or_exception):
- if isinstance(message_or_exception, str):
- super(FileSystemException, self).__init__(message_or_exception)
- elif isinstance(message_or_exception, Exception):
- self.caused_by = message_or_exception
- def getStatus(self):
- """
- Get error code. The code can be standard TCF error code or
- one of service specific codes, see STATUS_*.
- @return error code.
- """
- raise NotImplementedError("Abstract methods")
-
-class FileSystemService(services.Service):
- def getName(self):
- return NAME
-
- def open(self, file_name, flags, attrs, done):
- """
- Open or create a file on a remote system.
-
- @param file_name specifies the file name. See 'File Names' for more information.
- @param flags is a bit mask of TCF_O_* flags.
- @param attrs specifies the initial attributes for the file.
- Default values will be used for those attributes that are not specified.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def close(self, handle, done):
- """
- Close a file on a remote system.
-
- @param handle is a handle previously returned in the response to
- open() or opendir().
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def read(self, handle, offset, len, done):
- """
- Read bytes from an open file.
- In response to this request, the server will read as many bytes as it
- can from the file (up to 'len'), and return them in a byte array.
- If an error occurs or EOF is encountered, the server may return
- fewer bytes then requested. Call back method doneRead() argument 'error'
- will be not None in case of error, and argument 'eof' will be
- True in case of EOF. For normal disk files, it is guaranteed
- that this will read the specified number of bytes, or up to end of file
- or error. For e.g. device files this may return fewer bytes than requested.
-
- @param handle is an open file handle returned by open().
- @param offset is the offset (in bytes) relative
- to the beginning of the file from where to start reading.
- If offset < 0 then reading starts from current position in the file.
- @param len is the maximum number of bytes to read.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def write(self, handle, offset, data, data_pos, data_size, done):
- """
- Write bytes into an open file.
- The write will extend the file if writing beyond the end of the file.
- It is legal to write way beyond the end of the file the semantics
- are to write zeroes from the end of the file to the specified offset
- and then the data.
-
- @param handle is an open file handle returned by open().
- @param offset is the offset (in bytes) relative
- to the beginning of the file from where to start writing.
- If offset < 0 then writing starts from current position in the file.
- @param data is byte array that contains data for writing.
- @param data_pos if offset in 'data' of first byte to write.
- @param data_size is the number of bytes to write.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def stat(self, path, done):
- """
- Retrieve file attributes.
-
- @param path - specifies the file system object for which
- status is to be returned.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def lstat(self, path, done):
- """
- Retrieve file attributes.
- Unlike 'stat()', 'lstat()' does not follow symbolic links.
-
- @param path - specifies the file system object for which
- status is to be returned.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def fstat(self, handle, done):
- """
- Retrieve file attributes for an open file (identified by the file handle).
-
- @param handle is a file handle returned by 'open()'.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def setstat(self, path, attrs, done):
- """
- Set file attributes.
- This request is used for operations such as changing the ownership,
- permissions or access times, as well as for truncating a file.
- An error will be returned if the specified file system object does
- not exist or the user does not have sufficient rights to modify the
- specified attributes.
-
- @param path specifies the file system object (e.g. file or directory)
- whose attributes are to be modified.
- @param attrs specifies the modifications to be made to file attributes.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def fsetstat(self, handle, attrs, done):
- """
- Set file attributes for an open file (identified by the file handle).
- This request is used for operations such as changing the ownership,
- permissions or access times, as well as for truncating a file.
-
- @param handle is a file handle returned by 'open()'.
- @param attrs specifies the modifications to be made to file attributes.
- @param done is call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def opendir(self, path, done):
- """
- The opendir() command opens a directory for reading.
- Once the directory has been successfully opened, files (and
- directories) contained in it can be listed using readdir() requests.
- When the client no longer wishes to read more names from the
- directory, it SHOULD call close() for the handle. The handle
- should be closed regardless of whether an error has occurred or not.
-
- @param path - name of the directory to be listed (without any trailing slash).
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def readdir(self, handle, done):
- """
- The files in a directory can be listed using the opendir() and
- readdir() requests. Each readdir() request returns one
- or more file names with full file attributes for each file. The
- client should call readdir() repeatedly until it has found the
- file it is looking for or until the server responds with a
- message indicating an error or end of file. The client should then
- close the handle using the close() request.
- Note: directory entries "." and ".." are NOT included into readdir()
- response.
- @param handle - file handle created by opendir()
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def mkdir(self, path, attrs, done):
- """
- Create a directory on the server.
-
- @param path - specifies the directory to be created.
- @param attrs - new directory attributes.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def rmdir(self, path, done):
- """
- Remove a directory.
- An error will be returned if no directory
- with the specified path exists, or if the specified directory is not
- empty, or if the path specified a file system object other than a
- directory.
-
- @param path - specifies the directory to be removed.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def roots(self, done):
- """
- Retrieve file system roots - top level file system objects.
- UNIX file system can report just one root with path "/". Other types of systems
- can have more the one root. For example, Windows server can return multiple roots:
- one per disc (e.g. "/C:/", "/D:/", etc.). Note: even Windows implementation of
- the service must use forward slash as directory separator, and must start
- absolute path with "/". Server should implement proper translation of
- protocol file names to OS native names and back.
-
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def remove(self, file_name, done):
- """
- Remove a file or symbolic link.
- This request cannot be used to remove directories.
-
- @param file_name is the name of the file to be removed.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def realpath(self, path, done):
- """
- Canonicalize any given path name to an absolute path.
- This is useful for converting path names containing ".." components or
- relative pathnames without a leading slash into absolute paths.
-
- @param path specifies the path name to be canonicalized.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def rename(self, old_path, new_path, done):
- """
- Rename a file.
- It is an error if there already exists a file
- with the name specified by 'new_path'. The server may also fail rename
- requests in other situations, for example if 'old_path' and 'new_path'
- point to different file systems on the server.
-
- @param old_path is the name of an existing file or directory.
- @param new_path is the new name for the file or directory.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def readlink(self, path, done):
- """
- Read the target of a symbolic link.
-
- @param path specifies the path name of the symbolic link to be read.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def symlink(self, link_path, target_path, done):
- """
- Create a symbolic link on the server.
-
- @param link_path specifies the path name of the symbolic link to be created.
- @param target_path specifies the target of the symbolic link.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def copy(self, src_path, dst_path, copy_permissions, copy_ownership, done):
- """
- Copy a file on remote system.
-
- @param src_path specifies the path name of the file to be copied.
- @param dst_path specifies destination file name.
- @param copy_permissions - if True then copy source file permissions.
- @param copy_ownership - if True then copy source file UID and GID.
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
- def user(self, done):
- """
- Retrieve information about user account, which is used by server
- to access file system on behalf of the client.
-
- @param done - result call back object.
- @return pending command handle.
- """
- raise NotImplementedError("Abstract methods")
-
-class DoneOpen(object):
- def doneOpen(self, token, error, handle):
- pass
-
-class DoneClose(object):
- def doneClose(self, token, error):
- pass
-
-class DoneRead(object):
- def doneRead(self, token, error, data, eof):
- pass
-
-class DoneWrite(object):
- def doneWrite(self, token, error):
- pass
-
-class DoneStat(object):
- def doneStat(self, token, error, attrs):
- pass
-
-class DoneSetStat(object):
- def doneSetStat(self, token, error):
- pass
-
-class DoneReadDir(object):
- def doneReadDir(self, token, error, entries, eof):
- pass
-
-class DoneMkDir(object):
- def doneMkDir(self, token, error):
- pass
-
-class DoneRemove(object):
- def doneRemove(self, token, error):
- pass
-
-class DoneRoots(object):
- def doneRoots(self, token, error, entries):
- pass
-
-class DoneRealPath(object):
- def doneRealPath(self, token, error, path):
- pass
-
-class DoneRename(object):
- def doneRename(self, token, error):
- pass
-
-class DoneReadLink(object):
- def doneReadLink(self, token, error, path):
- pass
-
-class DoneSymLink(object):
- def doneSymLink(self, token, error):
- pass
-
-class DoneCopy(object):
- def doneCopy(self, token, error):
- pass
-
-class DoneUser(object):
- def doneUser(self, token, error, real_uid, effective_uid, real_gid, effective_gid, home):
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+File System service provides file transfer (and more generally file
+system access) functionality in TCF. The service design is
+derived from SSH File Transfer Protocol specifications.
+
+ Request Synchronization and Reordering
+
+The protocol and implementations MUST process requests relating to
+the same file in the order in which they are received. In other
+words, if an application submits multiple requests to the server, the
+results in the responses will be the same as if it had sent the
+requests one at a time and waited for the response in each case. For
+example, the server may process non-overlapping read/write requests
+to the same file in parallel, but overlapping reads and writes cannot
+be reordered or parallelized. However, there are no ordering
+restrictions on the server for processing requests from two different
+file transfer connections. The server may interleave and parallelize
+them at will.
+
+There are no restrictions on the order in which responses to
+outstanding requests are delivered to the client, except that the
+server must ensure fairness in the sense that processing of no
+request will be indefinitely delayed even if the client is sending
+other requests so that there are multiple outstanding requests all
+the time.
+
+There is no limit on the number of outstanding (non-acknowledged)
+requests that the client may send to the server. In practice this is
+limited by the buffering available on the data stream and the queuing
+performed by the server. If the server's queues are full, it should
+not read any more data from the stream, and flow control will prevent
+the client from sending more requests.
+
+ File Names
+
+This protocol represents file names as strings. File names are
+assumed to use the slash ('/') character as a directory separator.
+
+File names starting with a slash are "absolute", and are relative to
+the root of the file system. Names starting with any other character
+are relative to the user's default directory (home directory). Client
+can use 'user()' command to retrieve current user home directory.
+
+Servers SHOULD interpret a path name component ".." as referring to
+the parent directory, and "." as referring to the current directory.
+If the server implementation limits access to certain parts of the
+file system, it must be extra careful in parsing file names when
+enforcing such restrictions. There have been numerous reported
+security bugs where a ".." in a path name has allowed access outside
+the intended area.
+
+An empty path name is valid, and it refers to the user's default
+directory (usually the user's home directory).
+
+Otherwise, no syntax is defined for file names by this specification.
+Clients should not make any other assumptions however, they can
+splice path name components returned by readdir() together
+using a slash ('/') as the separator, and that will work as expected.
+"""
+
+from tcf import services
+
+# Service name.
+NAME = "FileSystem"
+
+# Flags to be used with open() method.
+
+# Open the file for reading.
+TCF_O_READ = 0x00000001
+
+# Open the file for writing. If both this and TCF_O_READ are
+# specified, the file is opened for both reading and writing.
+TCF_O_WRITE = 0x00000002
+
+# Force all writes to append data at the end of the file.
+TCF_O_APPEND = 0x00000004
+
+# If this flag is specified, then a new file will be created if one
+# does not already exist (if TCF_O_TRUNC is specified, the new file will
+# be truncated to zero length if it previously exists).
+TCF_O_CREAT = 0x00000008
+
+# Forces an existing file with the same name to be truncated to zero
+# length when creating a file by specifying TCF_O_CREAT.
+# TCF_O_CREAT MUST also be specified if this flag is used.
+TCF_O_TRUNC = 0x00000010
+
+# Causes the request to fail if the named file already exists.
+# TCF_O_CREAT MUST also be specified if this flag is used.
+TCF_O_EXCL = 0x00000020
+
+# Flags to be used together with FileAttrs.
+# The flags specify which of the fields are present. Those fields
+# for which the corresponding flag is not set are not present (not
+# included in the message).
+ATTR_SIZE = 0x00000001
+ATTR_UIDGID = 0x00000002
+ATTR_PERMISSIONS = 0x00000004
+ATTR_ACMODTIME = 0x00000008
+
+class FileAttrs(object):
+ """
+ FileAttrs is used both when returning file attributes from
+ the server and when sending file attributes to the server. When
+ sending it to the server, the flags field specifies which attributes
+ are included, and the server will use default values for the
+ remaining attributes (or will not modify the values of remaining
+ attributes). When receiving attributes from the server, the flags
+ specify which attributes are included in the returned data. The
+ server normally returns all attributes it knows about.
+
+ Fields:
+ The 'flags' specify which of the fields are present.
+ The 'size' field specifies the size of the file in bytes.
+ The 'uid' and 'gid' fields contain numeric Unix-like user and group
+ identifiers, respectively.
+ The 'permissions' field contains a bit mask of file permissions as
+ defined by posix [1].
+ The 'atime' and 'mtime' contain the access and modification times of
+ the files, respectively. They are represented as milliseconds from
+ midnight Jan 1, 1970 in UTC.
+ attributes - Additional (non-standard) attributes.
+ """
+ def __init__(self, flags, size, uid, gid, permissions, atime, mtime, attributes):
+ self.flags = flags
+ self.size = size
+ self.uid = uid
+ self.gid = gid
+ self.permissions = permissions
+ self.atime = atime
+ self.mtime = mtime
+ self.attributes = attributes
+
+ def isFile(self):
+ """
+ Determines if the file system object is a file on the remote file system.
+
+ @return True if and only if the object on the remote system can be considered to have "contents" that
+ have the potential to be read and written as a byte stream.
+ """
+ if (self.flags & ATTR_PERMISSIONS) == 0: return False
+ return (self.permissions & S_IFMT) == S_IFREG
+
+ def isDirectory(self):
+ """
+ Determines if the file system object is a directory on the remote file system.
+
+ @return True if and only if the object on the remote system is a directory.
+ That is, it contains entries that can be interpreted as other files.
+ """
+ if (self.flags & ATTR_PERMISSIONS) == 0: return False
+ return (self.permissions & S_IFMT) == S_IFDIR
+
+# The following flags are defined for the 'permissions' field:
+S_IFMT = 0170000 # bitmask for the file type bitfields
+S_IFSOCK = 0140000 # socket
+S_IFLNK = 0120000 # symbolic link
+S_IFREG = 0100000 # regular file
+S_IFBLK = 0060000 # block device
+S_IFDIR = 0040000 # directory
+S_IFCHR = 0020000 # character device
+S_IFIFO = 0010000 # fifo
+S_ISUID = 0004000 # set UID bit
+S_ISGID = 0002000 # set GID bit (see below)
+S_ISVTX = 0001000 # sticky bit (see below)
+S_IRWXU = 00700 # mask for file owner permissions
+S_IRUSR = 00400 # owner has read permission
+S_IWUSR = 00200 # owner has write permission
+S_IXUSR = 00100 # owner has execute permission
+S_IRWXG = 00070 # mask for group permissions
+S_IRGRP = 00040 # group has read permission
+S_IWGRP = 00020 # group has write permission
+S_IXGRP = 00010 # group has execute permission
+S_IRWXO = 00007 # mask for permissions for others (not in group)
+S_IROTH = 00004 # others have read permission
+S_IWOTH = 00002 # others have write permission
+S_IXOTH = 00001 # others have execute permission
+
+class DirEntry(object):
+ """
+ Directory entry.
+ Fields:
+ 'filename' is a file name being returned. It is a relative name within
+ the directory, without any path components
+ 'longname' is an expanded format for the file name, similar to what
+ is returned by "ls -l" on Unix systems.
+ The format of the 'longname' field is unspecified by this protocol.
+ It MUST be suitable for use in the output of a directory listing
+ command (in fact, the recommended operation for a directory listing
+ command is to simply display this data). However, clients SHOULD NOT
+ attempt to parse the longname field for file attributes they SHOULD
+ use the attrs field instead.
+ 'attrs' is the attributes of the file.
+ """
+ def __init__(self, filename, longname, attrs):
+ self.filename = filename
+ self.longname = longname
+ self.attrs = attrs
+
+class FileHandle(object):
+ def __init__(self, service, id):
+ self.service = service
+ self.id = id
+
+ def getService(self):
+ return self.service
+
+ def __str__(self):
+ return "[File Handle '%s'" % self.id
+
+# Service specific error codes.
+
+# Indicates end-of-file condition for read() it means that no
+# more data is available in the file, and for readdir() it
+# indicates that no more files are contained in the directory.
+STATUS_EOF = 0x10001
+
+# This code is returned when a reference is made to a file which
+# should exist but doesn't.
+STATUS_NO_SUCH_FILE = 0x10002
+
+# is returned when the authenticated user does not have sufficient
+# permissions to perform the operation.
+STATUS_PERMISSION_DENIED = 0x10003
+
+class FileSystemException(IOError):
+ """
+ The class to represent File System error reports.
+ """
+ def __init__(self, message_or_exception):
+ if isinstance(message_or_exception, str):
+ super(FileSystemException, self).__init__(message_or_exception)
+ elif isinstance(message_or_exception, Exception):
+ self.caused_by = message_or_exception
+ def getStatus(self):
+ """
+ Get error code. The code can be standard TCF error code or
+ one of service specific codes, see STATUS_*.
+ @return error code.
+ """
+ raise NotImplementedError("Abstract methods")
+
+class FileSystemService(services.Service):
+ def getName(self):
+ return NAME
+
+ def open(self, file_name, flags, attrs, done):
+ """
+ Open or create a file on a remote system.
+
+ @param file_name specifies the file name. See 'File Names' for more information.
+ @param flags is a bit mask of TCF_O_* flags.
+ @param attrs specifies the initial attributes for the file.
+ Default values will be used for those attributes that are not specified.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def close(self, handle, done):
+ """
+ Close a file on a remote system.
+
+ @param handle is a handle previously returned in the response to
+ open() or opendir().
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def read(self, handle, offset, len, done):
+ """
+ Read bytes from an open file.
+ In response to this request, the server will read as many bytes as it
+ can from the file (up to 'len'), and return them in a byte array.
+ If an error occurs or EOF is encountered, the server may return
+ fewer bytes then requested. Call back method doneRead() argument 'error'
+ will be not None in case of error, and argument 'eof' will be
+ True in case of EOF. For normal disk files, it is guaranteed
+ that this will read the specified number of bytes, or up to end of file
+ or error. For e.g. device files this may return fewer bytes than requested.
+
+ @param handle is an open file handle returned by open().
+ @param offset is the offset (in bytes) relative
+ to the beginning of the file from where to start reading.
+ If offset < 0 then reading starts from current position in the file.
+ @param len is the maximum number of bytes to read.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def write(self, handle, offset, data, data_pos, data_size, done):
+ """
+ Write bytes into an open file.
+ The write will extend the file if writing beyond the end of the file.
+ It is legal to write way beyond the end of the file the semantics
+ are to write zeroes from the end of the file to the specified offset
+ and then the data.
+
+ @param handle is an open file handle returned by open().
+ @param offset is the offset (in bytes) relative
+ to the beginning of the file from where to start writing.
+ If offset < 0 then writing starts from current position in the file.
+ @param data is byte array that contains data for writing.
+ @param data_pos if offset in 'data' of first byte to write.
+ @param data_size is the number of bytes to write.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def stat(self, path, done):
+ """
+ Retrieve file attributes.
+
+ @param path - specifies the file system object for which
+ status is to be returned.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def lstat(self, path, done):
+ """
+ Retrieve file attributes.
+ Unlike 'stat()', 'lstat()' does not follow symbolic links.
+
+ @param path - specifies the file system object for which
+ status is to be returned.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def fstat(self, handle, done):
+ """
+ Retrieve file attributes for an open file (identified by the file handle).
+
+ @param handle is a file handle returned by 'open()'.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def setstat(self, path, attrs, done):
+ """
+ Set file attributes.
+ This request is used for operations such as changing the ownership,
+ permissions or access times, as well as for truncating a file.
+ An error will be returned if the specified file system object does
+ not exist or the user does not have sufficient rights to modify the
+ specified attributes.
+
+ @param path specifies the file system object (e.g. file or directory)
+ whose attributes are to be modified.
+ @param attrs specifies the modifications to be made to file attributes.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def fsetstat(self, handle, attrs, done):
+ """
+ Set file attributes for an open file (identified by the file handle).
+ This request is used for operations such as changing the ownership,
+ permissions or access times, as well as for truncating a file.
+
+ @param handle is a file handle returned by 'open()'.
+ @param attrs specifies the modifications to be made to file attributes.
+ @param done is call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def opendir(self, path, done):
+ """
+ The opendir() command opens a directory for reading.
+ Once the directory has been successfully opened, files (and
+ directories) contained in it can be listed using readdir() requests.
+ When the client no longer wishes to read more names from the
+ directory, it SHOULD call close() for the handle. The handle
+ should be closed regardless of whether an error has occurred or not.
+
+ @param path - name of the directory to be listed (without any trailing slash).
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def readdir(self, handle, done):
+ """
+ The files in a directory can be listed using the opendir() and
+ readdir() requests. Each readdir() request returns one
+ or more file names with full file attributes for each file. The
+ client should call readdir() repeatedly until it has found the
+ file it is looking for or until the server responds with a
+ message indicating an error or end of file. The client should then
+ close the handle using the close() request.
+ Note: directory entries "." and ".." are NOT included into readdir()
+ response.
+ @param handle - file handle created by opendir()
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def mkdir(self, path, attrs, done):
+ """
+ Create a directory on the server.
+
+ @param path - specifies the directory to be created.
+ @param attrs - new directory attributes.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def rmdir(self, path, done):
+ """
+ Remove a directory.
+ An error will be returned if no directory
+ with the specified path exists, or if the specified directory is not
+ empty, or if the path specified a file system object other than a
+ directory.
+
+ @param path - specifies the directory to be removed.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def roots(self, done):
+ """
+ Retrieve file system roots - top level file system objects.
+ UNIX file system can report just one root with path "/". Other types of systems
+ can have more the one root. For example, Windows server can return multiple roots:
+ one per disc (e.g. "/C:/", "/D:/", etc.). Note: even Windows implementation of
+ the service must use forward slash as directory separator, and must start
+ absolute path with "/". Server should implement proper translation of
+ protocol file names to OS native names and back.
+
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def remove(self, file_name, done):
+ """
+ Remove a file or symbolic link.
+ This request cannot be used to remove directories.
+
+ @param file_name is the name of the file to be removed.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def realpath(self, path, done):
+ """
+ Canonicalize any given path name to an absolute path.
+ This is useful for converting path names containing ".." components or
+ relative pathnames without a leading slash into absolute paths.
+
+ @param path specifies the path name to be canonicalized.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def rename(self, old_path, new_path, done):
+ """
+ Rename a file.
+ It is an error if there already exists a file
+ with the name specified by 'new_path'. The server may also fail rename
+ requests in other situations, for example if 'old_path' and 'new_path'
+ point to different file systems on the server.
+
+ @param old_path is the name of an existing file or directory.
+ @param new_path is the new name for the file or directory.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def readlink(self, path, done):
+ """
+ Read the target of a symbolic link.
+
+ @param path specifies the path name of the symbolic link to be read.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def symlink(self, link_path, target_path, done):
+ """
+ Create a symbolic link on the server.
+
+ @param link_path specifies the path name of the symbolic link to be created.
+ @param target_path specifies the target of the symbolic link.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def copy(self, src_path, dst_path, copy_permissions, copy_ownership, done):
+ """
+ Copy a file on remote system.
+
+ @param src_path specifies the path name of the file to be copied.
+ @param dst_path specifies destination file name.
+ @param copy_permissions - if True then copy source file permissions.
+ @param copy_ownership - if True then copy source file UID and GID.
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+ def user(self, done):
+ """
+ Retrieve information about user account, which is used by server
+ to access file system on behalf of the client.
+
+ @param done - result call back object.
+ @return pending command handle.
+ """
+ raise NotImplementedError("Abstract methods")
+
+class DoneOpen(object):
+ def doneOpen(self, token, error, handle):
+ pass
+
+class DoneClose(object):
+ def doneClose(self, token, error):
+ pass
+
+class DoneRead(object):
+ def doneRead(self, token, error, data, eof):
+ pass
+
+class DoneWrite(object):
+ def doneWrite(self, token, error):
+ pass
+
+class DoneStat(object):
+ def doneStat(self, token, error, attrs):
+ pass
+
+class DoneSetStat(object):
+ def doneSetStat(self, token, error):
+ pass
+
+class DoneReadDir(object):
+ def doneReadDir(self, token, error, entries, eof):
+ pass
+
+class DoneMkDir(object):
+ def doneMkDir(self, token, error):
+ pass
+
+class DoneRemove(object):
+ def doneRemove(self, token, error):
+ pass
+
+class DoneRoots(object):
+ def doneRoots(self, token, error, entries):
+ pass
+
+class DoneRealPath(object):
+ def doneRealPath(self, token, error, path):
+ pass
+
+class DoneRename(object):
+ def doneRename(self, token, error):
+ pass
+
+class DoneReadLink(object):
+ def doneReadLink(self, token, error, path):
+ pass
+
+class DoneSymLink(object):
+ def doneSymLink(self, token, error):
+ pass
+
+class DoneCopy(object):
+ def doneCopy(self, token, error):
+ pass
+
+class DoneUser(object):
+ def doneUser(self, token, error, real_uid, effective_uid, real_gid, effective_gid, home):
+ pass
diff --git a/python/src/tcf/services/linenumbers.py b/python/src/tcf/services/linenumbers.py
index d026ecd12..fe3703def 100644
--- a/python/src/tcf/services/linenumbers.py
+++ b/python/src/tcf/services/linenumbers.py
@@ -1,132 +1,132 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Line numbers service associates locations in the source files with the corresponding
-machine instruction addresses in the executable object.
-"""
-
-from tcf import services
-
-NAME = "LineNumbers"
-
-class CodeArea(object):
- """
- A CodeArea represents a continues area in source text mapped to
- continues range of code addresses.
- Line and columns are counted starting from 1.
- File name can be a relative path, in this case the client should
- use the CodeArea directory name as origin for the path.
- File and directory names are valid on a host where code was compiled.
- It is client responsibility to map names to local host file system.
- """
- def __init__(self, directory, file, start_line, start_column,
- end_line, end_column, start_address, end_address, isa,
- is_statement, basic_block, prologue_end, epilogue_begin):
- self.directory = directory
- self.file = file
- self.start_line = start_line
- self.start_column = start_column
- self.end_line = end_line
- self.end_column = end_column
- self.start_address = start_address
- self.end_address = end_address
- self.isa = isa
- self.is_statement = is_statement
- self.basic_block = basic_block
- self.prologue_end = prologue_end
- self.epilogue_begin = epilogue_begin
-
- def __eq__(self, o):
- if self is o: return True
- if not isinstance(o, CodeArea): return False
- if self.start_line != o.start_line: return False
- if self.start_column != o.start_column: return False
- if self.end_line != o.end_line: return False
- if self.end_column != o.end_column: return False
- if self.isa != o.isa: return False
- if self.is_statement != o.is_statement: return False
- if self.basic_block != o.basic_block: return False
- if self.prologue_end != o.prologue_end: return False
- if self.epilogue_begin != o.epilogue_begin: return False
- if self.start_address != o.start_address: return False
- if self.end_address != o.end_address: return False
- if self.file != o.file: return False
- if self.directory != o.directory: return False
- return True
-
- def __hash__(self):
- h = 0
- if file: h += hash(file)
- return h + self.start_line + self.start_column + self.end_line + self.end_column
-
- def __str__(self):
- import cStringIO
- bf = cStringIO.StringIO()
- bf.write('[')
- if self.directory:
- bf.write(self.directory)
- bf.write(':')
- if self.file:
- bf.write(self.file)
- bf.write(':')
- bf.write(str(self.start_line))
- if self.start_column:
- bf.write('.')
- bf.write(str(self.start_column))
- bf.write("..")
- bf.write(str(self.end_line))
- if self.end_column:
- bf.write('.')
- bf.write(str(self.end_column))
- bf.write(" -> ")
- if self.start_address:
- bf.write("0x")
- bf.write(hex(self.start_address))
- else:
- bf.write('0')
- bf.write("..")
- if self.end_address:
- bf.write("0x")
- bf.write(hex(self.end_address))
- else:
- bf.write('0')
- if self.isa:
- bf.write(",isa ")
- bf.write(str(self.isa))
- if self.is_statement:
- bf.write(",statement")
- if self.basic_block:
- bf.write(",basic block")
- if self.prologue_end:
- bf.write(",prologue end")
- if self.epilogue_begin:
- bf.write(",epilogue begin")
- bf.write(']')
- return bf.getvalue()
-
-class LineNumbersService(services.Service):
- def getName(self):
- return NAME
-
- def mapToSource(self, context_id, start_address, end_address, done):
- raise NotImplementedError("Abstract method")
-
- def mapToMemory(self, context_id, file, line, column, done):
- raise NotImplementedError("Abstract method")
-
-class DoneMapToSource(object):
- def doneMapToSource(self, token, error, areas):
- pass
-
-class DoneMapToMemory(object):
- def doneMapToMemory(self, token, error, areas):
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Line numbers service associates locations in the source files with the corresponding
+machine instruction addresses in the executable object.
+"""
+
+from tcf import services
+
+NAME = "LineNumbers"
+
+class CodeArea(object):
+ """
+ A CodeArea represents a continues area in source text mapped to
+ continues range of code addresses.
+ Line and columns are counted starting from 1.
+ File name can be a relative path, in this case the client should
+ use the CodeArea directory name as origin for the path.
+ File and directory names are valid on a host where code was compiled.
+ It is client responsibility to map names to local host file system.
+ """
+ def __init__(self, directory, file, start_line, start_column,
+ end_line, end_column, start_address, end_address, isa,
+ is_statement, basic_block, prologue_end, epilogue_begin):
+ self.directory = directory
+ self.file = file
+ self.start_line = start_line
+ self.start_column = start_column
+ self.end_line = end_line
+ self.end_column = end_column
+ self.start_address = start_address
+ self.end_address = end_address
+ self.isa = isa
+ self.is_statement = is_statement
+ self.basic_block = basic_block
+ self.prologue_end = prologue_end
+ self.epilogue_begin = epilogue_begin
+
+ def __eq__(self, o):
+ if self is o: return True
+ if not isinstance(o, CodeArea): return False
+ if self.start_line != o.start_line: return False
+ if self.start_column != o.start_column: return False
+ if self.end_line != o.end_line: return False
+ if self.end_column != o.end_column: return False
+ if self.isa != o.isa: return False
+ if self.is_statement != o.is_statement: return False
+ if self.basic_block != o.basic_block: return False
+ if self.prologue_end != o.prologue_end: return False
+ if self.epilogue_begin != o.epilogue_begin: return False
+ if self.start_address != o.start_address: return False
+ if self.end_address != o.end_address: return False
+ if self.file != o.file: return False
+ if self.directory != o.directory: return False
+ return True
+
+ def __hash__(self):
+ h = 0
+ if file: h += hash(file)
+ return h + self.start_line + self.start_column + self.end_line + self.end_column
+
+ def __str__(self):
+ import cStringIO
+ bf = cStringIO.StringIO()
+ bf.write('[')
+ if self.directory:
+ bf.write(self.directory)
+ bf.write(':')
+ if self.file:
+ bf.write(self.file)
+ bf.write(':')
+ bf.write(str(self.start_line))
+ if self.start_column:
+ bf.write('.')
+ bf.write(str(self.start_column))
+ bf.write("..")
+ bf.write(str(self.end_line))
+ if self.end_column:
+ bf.write('.')
+ bf.write(str(self.end_column))
+ bf.write(" -> ")
+ if self.start_address:
+ bf.write("0x")
+ bf.write(hex(self.start_address))
+ else:
+ bf.write('0')
+ bf.write("..")
+ if self.end_address:
+ bf.write("0x")
+ bf.write(hex(self.end_address))
+ else:
+ bf.write('0')
+ if self.isa:
+ bf.write(",isa ")
+ bf.write(str(self.isa))
+ if self.is_statement:
+ bf.write(",statement")
+ if self.basic_block:
+ bf.write(",basic block")
+ if self.prologue_end:
+ bf.write(",prologue end")
+ if self.epilogue_begin:
+ bf.write(",epilogue begin")
+ bf.write(']')
+ return bf.getvalue()
+
+class LineNumbersService(services.Service):
+ def getName(self):
+ return NAME
+
+ def mapToSource(self, context_id, start_address, end_address, done):
+ raise NotImplementedError("Abstract method")
+
+ def mapToMemory(self, context_id, file, line, column, done):
+ raise NotImplementedError("Abstract method")
+
+class DoneMapToSource(object):
+ def doneMapToSource(self, token, error, areas):
+ pass
+
+class DoneMapToMemory(object):
+ def doneMapToMemory(self, token, error, areas):
+ pass
diff --git a/python/src/tcf/services/local/LocatorService.py b/python/src/tcf/services/local/LocatorService.py
index 5d8f43bc2..5a9271548 100644
--- a/python/src/tcf/services/local/LocatorService.py
+++ b/python/src/tcf/services/local/LocatorService.py
@@ -1,807 +1,807 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Locator service uses transport layer to search
-for peers and to collect and maintain up-to-date
-data about peer's attributes.
-"""
-
-import threading, time, socket, cStringIO
-from tcf.services import locator
-from tcf.util import logging
-from tcf.channel import fromJSONSequence, toJSONSequence
-from tcf.channel.ChannelProxy import ChannelProxy
-from tcf import protocol, services, channel, peer, errors
-
-# Flag indicating whether tracing of the the discovery activity is enabled.
-__TRACE_DISCOVERY__ = False
-
-class SubNet(object):
- def __init__(self, prefix_length, address, broadcast):
- self.prefix_length = prefix_length
- self.address = address
- self.broadcast = broadcast
- self.last_slaves_req_time = 0
- def contains(self, addr):
- if addr is None or self.address is None: return False
- a1 = addr.getAddress()
- a2 = self.address.getAddress()
- if len(a1) != len(a2): return False
- i = 0
- if self.prefix_length <= len(a1) * 8:
- l = self.prefix_length
- else:
- l = len(a1) * 8
- while i + 8 <= l:
- n = i / 8
- if a1[n] != a2[n]: return False
- i += 8
- while i < l:
- n = i / 8
- m = 1 << (7 - i % 8)
- if (a1[n] & m) != (a2[n] & m): return False
- i += 1
- return True
- def __eq__(self, o):
- if not isinstance(o, SubNet): return False
- return self.prefix_length == o.prefix_length and \
- self.broadcast == o.broadcast and \
- self.address == o.address
- def __hash__(self):
- return hash(self.address)
- def __str__(self):
- return "%s/%d" % (self.address.getHostAddress(), self.prefix_length)
-
-class Slave(object):
- # Time of last packet receiver from self slave
- last_packet_time = 0
- #Time of last REQ_SLAVES packet received from self slave
- last_req_slaves_time = 0
-
- def __init__(self, address, port):
- self.address = address
- self.port = port
- def __str__(self):
- return "%s/%d" % (self.address.getHostAddress(), self.port)
-
-class AddressCacheItem(object):
- address = None
- time_stamp = 0
- used = False
- def __init__(self, host):
- self.host = host
-
-class InetAddress(object):
- "Mimicking Java InetAddress class"
- def __init__(self, host, addr):
- self.host = host
- self.addr = addr
- def getAddress(self):
- return socket.inet_aton(self.addr)
- def getHostAddress(self):
- return self.addr
- def __eq__(self, other):
- if not isinstance(other, InetAddress): return False
- return self.addr == other.addr
- def __str__(self):
- return "%s/%s" % (self.host or "", self.addr)
-
-class InputPacket(object):
- "Wrapper for UDP packet data."
- def __init__(self, data, addr, port):
- self.data = data
- self.addr = addr
- self.port = port
- def getLength(self):
- return len(self.data)
- def getData(self):
- return self.data
- def getPort(self):
- return self.port
- def getAddress(self):
- return self.addr
- def __str__(self):
- return "[address=%s,port=%d,data=\"%s\"]" % (self.getAddress(), self.getPort(), self.data)
-
-DISCOVEY_PORT = 1534
-MAX_PACKET_SIZE = 9000 - 40 - 8
-PREF_PACKET_SIZE = 1500 - 40 - 8
-
-# TODO: research usage of DNS-SD (DNS Service Discovery) to discover TCF peers
-class LocatorService(locator.LocatorService):
- locator = None
- peers = {} # str->Peer
- listeners = [] # list of LocatorListener
- error_log = set() # set of str
-
- addr_cache = {} # str->AddressCacheItem
- addr_request = False
- local_peer = None
- last_master_packet_time = 0
-
- @classmethod
- def getLocalPeer(cls):
- return cls.local_peer
-
- @classmethod
- def getListeners(cls):
- return cls.listeners[:]
-
- @classmethod
- def startup(cls):
- if cls.locator:
- cls.locator._startup()
-
- @classmethod
- def shutdown(cls):
- if cls.locator:
- cls.locator._shutdown()
-
- def __init__(self):
- self._error_log_lock = threading.RLock()
- self._alive = False
- LocatorService.locator = self
- LocatorService.local_peer = peer.LocalPeer()
-
- def _startup(self):
- if self._alive: return
- self._alive = True
- self._addr_cache_lock = threading.Condition()
- self.subnets = set()
- self.slaves = []
- self.inp_buf = bytearray(MAX_PACKET_SIZE)
- self.out_buf = bytearray(MAX_PACKET_SIZE)
- service = self
- class TimerThread(threading.Thread):
- def __init__(self, callable):
- self._callable = callable
- super(TimerThread, self).__init__()
- def run(self):
- while service._alive:
- try:
- time.sleep(locator.DATA_RETENTION_PERIOD / 4 / 1000.)
- protocol.invokeAndWait(self._callable)
- except RuntimeError:
- # TCF event dispatch is shut down
- return
- except Exception as x:
- service._log("Unhandled exception in TCF discovery timer thread", x)
- self.timer_thread = TimerThread(self.__refresh_timer)
- class DNSLookupThread(threading.Thread):
- def run(self):
- while service._alive:
- try:
- itemSet = None
- with service._addr_cache_lock:
- if not LocatorService.addr_request:
- service._addr_cache_lock.wait(locator.DATA_RETENTION_PERIOD)
- msec = int(time.time() * 1000)
- for host, a in LocatorService.addr_cache.items():
- if a.time_stamp + locator.DATA_RETENTION_PERIOD * 10 < msec:
- if a.used:
- if itemSet is None: itemSet = set()
- itemSet.add(a)
- else:
- del LocatorService.addr_cache[host]
- LocatorService.addr_request = False
- if itemSet is not None:
- for a in itemSet:
- addr = None
- try:
- addr = socket.gethostbyname(a.host)
- except socket.gaierror:
- pass
- with service._addr_cache_lock:
- if addr is None:
- a.address = None
- else:
- a.address = InetAddress(a.host, addr)
- a.time_stamp = msec
- a.used = False
- except Exception as x:
- service._log("Unhandled exception in TCF discovery DNS lookup thread", x)
- self.dns_lookup_thread = DNSLookupThread()
- class InputThread(threading.Thread):
- def __init__(self, callable):
- self._callable = callable
- super(InputThread, self).__init__()
- def run(self):
- try:
- while service._alive:
- sock = service.socket
- try:
- data, addr = sock.recvfrom(MAX_PACKET_SIZE)
- p = InputPacket(data, InetAddress(None, addr[0]), addr[1])
- protocol.invokeAndWait(self._callable, p)
- except RuntimeError:
- # TCF event dispatch is shutdown
- return
- except socket.error as x:
- if sock != service.socket: continue
- # frequent error on windows, unknown reason
- if x.errno == 10054: continue
- port = sock.getsockname()[1]
- service._log("Cannot read from datagram socket at port %d" % port, x)
- time.sleep(2)
- except Exception as x:
- service._log("Unhandled exception in socket reading thread", x)
- self.input_thread = InputThread(self.__handleDatagramPacket)
- try:
- self.loopback_addr = InetAddress(None, "127.0.0.1")
- self.out_buf[0:8] = 'TCF%s\0\0\0\0' % locator.CONF_VERSION
- self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- try:
- self.socket.bind(('', DISCOVEY_PORT))
- if __TRACE_DISCOVERY__:
- logging.trace("Became the master agent (bound to port %d)" % self.socket.getsockname()[1])
- except socket.error as x:
- self.socket.bind(('', 0))
- if __TRACE_DISCOVERY__:
- logging.trace("Became a slave agent (bound to port %d)" % self.socket.getsockname()[1])
- self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- self.input_thread.setName("TCF Locator Receiver")
- self.timer_thread.setName("TCF Locator Timer")
- self.dns_lookup_thread.setName("TCF Locator DNS Lookup")
- self.input_thread.setDaemon(True)
- self.timer_thread.setDaemon(True)
- self.dns_lookup_thread.setDaemon(True)
- self.input_thread.start()
- self.timer_thread.start()
- self.dns_lookup_thread.start()
- class LocatorListener(locator.LocatorListener):
- def peerAdded(self, peer):
- service._sendPeerInfo(peer, None, 0)
- def peerChanged(self, peer):
- service._sendPeerInfo(peer, None, 0)
- self.listeners.append(LocatorListener())
- self.__refreshSubNetList()
- self.__sendPeersRequest(None, 0)
- self.__sendAll(None, 0, None, int(time.time() * 1000))
- except Exception as x:
- self._log("Cannot open UDP socket for TCF discovery protocol", x)
-
- def _shutdown(self):
- if self._alive:
- self._alive = False
-
- def __makeErrorReport(self, code, msg):
- err = {}
- err[errors.ERROR_TIME] = int(time.time() * 1000)
- err[errors.ERROR_CODE] = code
- err[errors.ERROR_FORMAT] = msg
- return err
-
- def __command(self, channel, token, name, data):
- try:
- if name == "redirect":
- peer_id = fromJSONSequence(data)[0]
- _peer = self.peers.get(peer_id)
- if _peer is None:
- error = self.__makeErrorReport(errors.TCF_ERROR_UNKNOWN_PEER, "Unknown peer ID")
- channel.sendResult(token, toJSONSequence((error,)))
- return
- channel.sendResult(token, toJSONSequence((None,)))
- if isinstance(_peer, peer.LocalPeer):
- channel.sendEvent(protocol.getLocator(), "Hello", toJSONSequence((channel.getLocalServices(),)))
- return
- ChannelProxy(channel, _peer.openChannel())
- elif name == "sync":
- channel.sendResult(token, None)
- elif name == "getPeers":
- arr = []
- for p in self.peers.values():
- arr.append(p.getAttributes())
- channel.sendResult(token, toJSONSequence((None, arr)))
- else:
- channel.rejectCommand(token)
- except Exception as x:
- channel.terminate(x)
-
- def _log(self, msg, x):
- if not self._alive: return
- # Don't report same error multiple times to avoid filling up the log file.
- with self._error_log_lock:
- if msg in self.error_log: return
- self.error_log.add(msg)
- protocol.log(msg, x)
-
- def __getInetAddress(self, host):
- if not host: return None
- with self._addr_cache_lock:
- i = self.addr_cache.get(host)
- if i is None:
- i = AddressCacheItem(host)
- ch = host[0]
- if ch == '[' or ch == ':' or ch >= '0' and ch <= '9':
- try:
- addr = socket.gethostbyname(host)
- i.address = InetAddress(host, addr)
- except socket.gaierror:
- pass
- i.time_stamp = int(time.time() * 1000)
- else:
- # socket.gethostbyname() can cause long delay - delegate to background thread
- LocatorService.addr_request = True
- self._addr_cache_lock.notify()
- self.addr_cache[host] = i
- i.used = True
- return i.address
-
- def __refresh_timer(self):
- tm = int(time.time() * 1000)
- # Cleanup slave table
- if self.slaves:
- i = 0
- while i < len(self.slaves):
- s = self.slaves[i]
- if s.last_packet_time + locator.DATA_RETENTION_PERIOD < tm:
- del self.slaves[i]
- else:
- i += 1
-
- # Cleanup peers table
- stale_peers = None
- for p in self.peers.values():
- if isinstance(p, peer.RemotePeer):
- if p.getLastUpdateTime() + locator.DATA_RETENTION_PERIOD < tm:
- if stale_peers == None: stale_peers = []
- stale_peers.append(p)
- if stale_peers is not None:
- for p in stale_peers: p.dispose()
-
- # Try to become a master
- port = self.socket.getsockname()[1]
- if port != DISCOVEY_PORT and \
- self.last_master_packet_time + locator.DATA_RETENTION_PERIOD / 2 <= tm:
- s0 = self.socket
- s1 = None
- try:
- s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s1.bind(DISCOVEY_PORT)
- s1.setsockopt(socket.SOL_UDP, socket.SO_BROADCAST, 1)
- self.socket = s1
- s0.close()
- except:
- pass
- self.__refreshSubNetList()
- if port != DISCOVEY_PORT:
- for subnet in self.subnets:
- self.__addSlave(subnet.address, port, tm, tm)
- self.__sendAll(None, 0, None, tm)
-
- def __addSlave(self, addr, port, timestamp, time_now):
- for s in self.slaves:
- if s.port == port and s.address == addr:
- if s.last_packet_time < timestamp: s.last_packet_time = timestamp
- return s
- s = Slave(addr, port)
- s.last_packet_time = timestamp
- self.slaves.append(s)
- self.__sendPeersRequest(addr, port)
- self.__sendAll(addr, port, s, time_now)
- self.__sendSlaveInfo(s, time_now)
- return s
-
- def __refreshSubNetList(self):
- subNetSet = set()
- try:
- self.__getSubNetList(subNetSet)
- except Exception as x:
- self._log("Cannot get list of network interfaces", x)
- for s in tuple(self.subnets):
- if s in subNetSet: continue
- self.subnets.remove(s)
- for s in subNetSet:
- if s in self.subnets: continue
- self.subnets.add(s)
- if __TRACE_DISCOVERY__:
- str = cStringIO.StringIO()
- str.write("Refreshed subnet list:")
- for subnet in self.subnets:
- str.write("\n\t* address=%s, broadcast=%s" % (subnet.address, subnet.broadcast))
- logging.trace(str.getvalue())
-
- def __getSubNetList(self, set):
- # TODO iterate over network interfaces to get proper broadcast addresses
- hostname = socket.gethostname()
- _, _, addresses = socket.gethostbyname_ex(hostname)
- if not "127.0.0.1" in addresses:
- addresses.append("127.0.0.1")
- for address in addresses:
- rawaddr = socket.inet_aton(address)
- if len(rawaddr) != 4: continue
- rawaddr = rawaddr[:3] + '\xFF'
- broadcast = socket.inet_ntoa(rawaddr)
- set.add(SubNet(24, InetAddress(hostname, address), InetAddress(None, broadcast)))
-
- def __getUTF8Bytes(self, s):
- return s.encode("UTF-8")
-
- # Used for tracing
- packetTypes = [
- None,
- "CONF_REQ_INFO",
- "CONF_PEER_INFO",
- "CONF_REQ_SLAVES",
- "CONF_SLAVES_INFO",
- "CONF_PEERS_REMOVED"
- ]
-
- def __sendDatagramPacket(self, subnet, size, addr, port):
- try:
- if addr is None:
- addr = subnet.broadcast
- port = DISCOVEY_PORT
- for slave in self.slaves:
- self.__sendDatagramPacket(subnet, size, slave.address, slave.port)
- if not subnet.contains(addr): return False
- if port == self.socket.getsockname()[1] and addr == subnet.address: return False
- self.socket.sendto(str(self.out_buf[:size]), (addr.getHostAddress(), port))
-
- if __TRACE_DISCOVERY__:
- map = None
- if self.out_buf[4] == locator.CONF_PEER_INFO:
- map = self.__parsePeerAttributes(self.out_buf, 8)
- elif self.out_buf[4] == locator.CONF_SLAVES_INFO:
- map = self.__parseIDs(self.out_buf, size)
- elif self.out_buf[4] == locator.CONF_PEERS_REMOVED:
- map = self.__parseIDs(self.out_buf, size)
- self.__traceDiscoveryPacket(False, self.packetTypes[self.out_buf[4]], map, addr, port)
- except Exception as x:
- self._log("Cannot send datagram packet to %s" % addr, x)
- return False
- return True
-
- def __parsePeerAttributes(self, data, size):
- """
- Parse peer attributes in CONF_PEER_INFO packet data
-
- @param data - the packet data
- @param size - the packet size
- @return a map containing the attributes
- """
- map = {}
- s = data[8:size - 8].decode("UTF-8")
- l = len(s)
- i = 0
- while i < l:
- i0 = i
- while i < l and s[i] != '=' and s[i] != '\0': i += 1
- i1 = i
- if i < l and s[i] == '=': i += 1
- i2 = i
- while i < l and s[i] != '\0': i += 1
- i3 = i
- if i < l and s[i] == '\0': i += 1
- key = s[i0:i1]
- val = s[i2:i3]
- map[key] = val
- return map
-
- def __parseIDs(self, data, size):
- """
- Parse list of IDs in CONF_SLAVES_INFO and CONF_PEERS_REMOVED packet data.
-
- @param data - the packet data
- @param size - the packet size
- @return a map containing the IDs
- """
- cnt = 0
- map = {}
- s = data[8:size - 8].decode("UTF-8")
- l = len(s)
- i = 0
- while i < l:
- i0 = i
- while i < l and s[i] != '\0': i += 1
- if i > i0:
- id = s[i0:i]
- map[str(cnt)] = id
- cnt += 1
- while i < l and s[i] == '\0': i += 1
- return map
-
- def __sendPeersRequest(self, addr, port):
- self.out_buf[4] = locator.CONF_REQ_INFO
- for subnet in self.subnets:
- self.__sendDatagramPacket(subnet, 8, addr, port)
-
- def _sendPeerInfo(self, _peer, addr, port):
- attrs = _peer.getAttributes()
- peer_addr = self.__getInetAddress(attrs.get(peer.ATTR_IP_HOST))
- if peer_addr is None: return
- if attrs.get(peer.ATTR_IP_PORT) is None: return
- self.out_buf[4] = locator.CONF_PEER_INFO
- i = 8
-
- for subnet in self.subnets:
- if isinstance(_peer, peer.RemotePeer):
- if self.socket.getsockname()[1] != DISCOVEY_PORT: return
- if not subnet.address == self.loopback_addr and not subnet.address == peer_addr: continue
- if not subnet.address == self.loopback_addr:
- if not subnet.contains(peer_addr): continue
- if i == 8:
- sb = cStringIO.StringIO()
- for key in attrs.keys():
- sb.write(key)
- sb.write('=')
- sb.write(attrs.get(key))
- sb.write('\0')
- bt = self.__getUTF8Bytes(sb.getvalue())
- if i + len(bt) > len(self.out_buf): return
- self.out_buf[i:i+len(bt)] = bt
- i += len(bt)
- if self.__sendDatagramPacket(subnet, i, addr, port): subnet.send_all_ok = True
-
- def __sendEmptyPacket(self, addr, port):
- self.out_buf[4] = locator.CONF_SLAVES_INFO
- for subnet in self.subnets:
- if subnet.send_all_ok: continue
- self.__sendDatagramPacket(subnet, 8, addr, port)
-
- def __sendAll(self, addr, port, sl, tm):
- for subnet in self.subnets: subnet.send_all_ok = False
- for peer in self.peers.values(): self._sendPeerInfo(peer, addr, port)
- if addr is not None and sl is not None and sl.last_req_slaves_time + locator.DATA_RETENTION_PERIOD >= tm:
- self.__sendSlavesInfo(addr, port, tm)
- self.__sendEmptyPacket(addr, port)
-
- def __sendSlavesRequest(self, subnet, addr, port):
- self.out_buf[4] = locator.CONF_REQ_SLAVES
- self.__sendDatagramPacket(subnet, 8, addr, port)
-
- def __sendSlaveInfo(self, x, tm):
- ttl = x.last_packet_time + locator.DATA_RETENTION_PERIOD - tm
- if ttl <= 0: return
- self.out_buf[4] = locator.CONF_SLAVES_INFO
- for subnet in self.subnets:
- if not subnet.contains(x.address): continue
- i = 8
- s = "%d:%s:%s" % (ttl, x.port, x.address.getHostAddress())
- bt = self.__getUTF8Bytes(s)
- self.out_buf[i:i+len(bt)] = bt
- i += len(bt)
- self.out_buf[i] = 0
- i += 1
- for y in self.slaves:
- if not subnet.contains(y.address): continue
- if y.last_req_slaves_time + locator.DATA_RETENTION_PERIOD < tm: continue
- self.__sendDatagramPacket(subnet, i, y.address, y.port)
-
- def __sendSlavesInfo(self, addr, port, tm):
- self.out_buf[4] = locator.CONF_SLAVES_INFO
- for subnet in self.subnets:
- if not subnet.contains(addr): continue
- i = 8
- for x in self.slaves:
- ttl = x.last_packet_time + locator.DATA_RETENTION_PERIOD - tm
- if ttl <= 0: return
- if x.port == port and x.address == addr: continue
- if not subnet.address == self.loopback_addr:
- if not subnet.contains(x.address): continue
- subnet.send_all_ok = True
- s = "%d:%s:%s" % (x.last_packet_time, x.port, x.address.getHostAddress())
- bt = self.__getUTF8Bytes(s)
- if i > 8 and i + len(bt) >= PREF_PACKET_SIZE:
- self.__sendDatagramPacket(subnet, i, addr, port)
- i = 8
- self.out_buf[i:len(bt)] = bt
- i += len(bt)
- self.out_buf[i] = 0
- i += 1
- if i > 8: self.__sendDatagramPacket(subnet, i, addr, port)
-
- def __isRemote(self, address, port):
- if port != self.socket.getsockname()[1]: return True
- for s in self.subnets:
- if s.address == address: return False
- return True
-
- def __handleDatagramPacket(self, p):
- try:
- tm = int(time.time() * 1000)
- buf = p.getData()
- len = p.getLength()
- if len < 8: return
- if buf[0] != 'T': return
- if buf[1] != 'C': return
- if buf[2] != 'F': return
- if buf[3] != locator.CONF_VERSION: return
- remote_port = p.getPort()
- remote_address = p.getAddress()
- if self.__isRemote(remote_address, remote_port):
- if buf[4] == locator.CONF_PEERS_REMOVED:
- self.__handlePeerRemovedPacket(p)
- else:
- sl = None
- if remote_port != DISCOVEY_PORT:
- sl = self.__addSlave(remote_address, remote_port, tm, tm)
- code = ord(buf[4])
- if code == locator.CONF_PEER_INFO:
- self.__handlePeerInfoPacket(p)
- elif code == locator.CONF_REQ_INFO:
- self.__handleReqInfoPacket(p, sl, tm)
- elif code == locator.CONF_SLAVES_INFO:
- self.__handleSlavesInfoPacket(p, tm)
- elif code == locator.CONF_REQ_SLAVES:
- self.__handleReqSlavesPacket(p, sl, tm)
- for subnet in self.subnets:
- if not subnet.contains(remote_address): continue
- delay = locator.DATA_RETENTION_PERIOD / 3
- if remote_port != DISCOVEY_PORT: delay = locator.DATA_RETENTION_PERIOD / 32
- elif subnet.address != remote_address: delay = locator.DATA_RETENTION_PERIOD / 2
- if subnet.last_slaves_req_time + delay <= tm:
- self.__sendSlavesRequest(subnet, remote_address, remote_port)
- subnet.last_slaves_req_time = tm
- if subnet.address == remote_address and remote_port == DISCOVEY_PORT:
- self.last_master_packet_time = tm
- except Exception as x:
- self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
-
- def __handlePeerInfoPacket(self, p):
- try:
- map = self.__parsePeerAttributes(p.getData(), p.getLength())
- if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_PEER_INFO", map, p)
- id = map.get(peer.ATTR_ID)
- if id is None: raise RuntimeError("Invalid peer info: no ID")
- ok = True
- host = map.get(peer.ATTR_IP_HOST)
- if host is not None:
- ok = False
- peer_addr = self.__getInetAddress(host)
- if peer_addr is not None:
- for subnet in self.subnets:
- if subnet.contains(peer_addr):
- ok = True
- break
- if ok:
- _peer = self.peers.get(id)
- if isinstance(_peer, peer.RemotePeer):
- _peer.updateAttributes(map)
- elif _peer is None:
- peer.RemotePeer(map)
- except Exception as x:
- self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
-
- def __handleReqInfoPacket(self, p, sl, tm):
- if __TRACE_DISCOVERY__:
- self.__traceDiscoveryPacket(True, "CONF_REQ_INFO", None, p)
- self.__sendAll(p.getAddress(), p.getPort(), sl, tm)
-
- def __handleSlavesInfoPacket(self, p, time_now):
- try:
- map = self.__parseIDs(p.getData(), p.getLength())
- if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_SLAVES_INFO", map, p)
- for s in map.values():
- i = 0
- l = len(s)
- time0 = i
- while i < l and s[i] != ':' and s[i] != '\0': i += 1
- time1 = i
- if i < l and s[i] == ':': i += 1
- port0 = i
- while i < l and s[i] != ':' and s[i] != '\0': i += 1
- port1 = i
- if i < l and s[i] == ':': i += 1
- host0 = i
- while i < l and s[i] != '\0': i += 1
- host1 = i
- port = int(s[port0:port1])
- timestamp = s[time0:time1]
- host = s[host0:host1]
- if port != DISCOVEY_PORT:
- addr = self.__getInetAddress(host)
- if addr is not None:
- delta = 10006030 # 30 minutes
- if len(timestamp) > 0:
- time_val = int(timestamp)
- else:
- time_val = time_now
- if time_val < 3600000:
- # Time stamp is "time to live" in milliseconds
- time_val = time_now + time_val / 1000 - locator.DATA_RETENTION_PERIOD
- elif time_val < time_now / 1000 + 50000000:
- # Time stamp is in seconds
- time_val= 1000
- else:
- # Time stamp is in milliseconds
- pass
- if time_val < time_now - delta or time_val > time_now + delta:
- msg = "Invalid slave info timestamp: %s -> %s" % (
- timestamp, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time_val/1000.)))
- self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), Exception(msg))
- time_val = time_now - locator.DATA_RETENTION_PERIOD / 2
- self.__addSlave(addr, port, time_val, time_now)
- except Exception as x:
- self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
-
- def __handleReqSlavesPacket(self, p, sl, tm):
- if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_REQ_SLAVES", None, p)
- if sl is not None: sl.last_req_slaves_time = tm
- self.__sendSlavesInfo(p.getAddress(), p.getPort(), tm)
-
- def __handlePeerRemovedPacket(self, p):
- try:
- map = self.__parseIDs(p.getData(), p.getLength())
- if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_PEERS_REMOVED", map, p)
- for id in map.values():
- _peer = self.peers.get(id)
- if isinstance(_peer, peer.RemotePeer): _peer.dispose()
- except Exception as x:
- self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
-
-
- @classmethod
- def getLocator(cls):
- return cls.locator
-
- def getPeers(self):
- assert protocol.isDispatchThread()
- return self.peers
-
- def redirect(self, peer, done):
- raise RuntimeError("Channel redirect cannot be done on local peer")
-
- def sync(self, done):
- raise RuntimeError("Channel sync cannot be done on local peer")
-
- def addListener(self, listener):
- assert listener is not None
- assert protocol.isDispatchThread()
- self.listeners.append(listener)
-
- def removeListener(self, listener):
- assert protocol.isDispatchThread()
- self.listeners.remove(listener)
-
- @classmethod
- def __traceDiscoveryPacket(cls, received, type, attrs, addr, port=None):
- """
- Log that a TCF Discovery packet has be sent or received. The trace is
- sent to stdout. This should be called only if the tracing has been turned
- on.
-
- @param received
- True if the packet was sent, otherwise it was received
- @param type
- a string specifying the type of packet, e.g., "CONF_PEER_INFO"
- @param attrs
- a set of attributes relevant to the type of packet (typically
- a peer's attributes)
- @param addr
- the network address the packet is being sent to
- @param port
- the port the packet is being sent to
- """
- assert __TRACE_DISCOVERY__
- if port is None:
- # addr is a InputPacket
- port = addr.getPort()
- addr = addr.getAddress()
- str = cStringIO.StringIO()
- str.write(type)
- str.write((" sent to ", " received from ")[received])
- str.write("%s/%s" % (addr, port))
- if attrs is not None:
- for key, value in attrs.items():
- str.write("\n\t%s=%s" % (key, value))
- logging.trace(str.getvalue())
-
-class LocatorServiceProvider(services.ServiceProvider):
- def getLocalService(self, _channel):
- class CommandServer(channel.CommandServer):
- def command(self, token, name, data):
- LocatorService.locator.command(channel, token, name, data)
- _channel.addCommandServer(LocatorService.locator, CommandServer())
- return (LocatorService.locator,)
-
-services.addServiceProvider(LocatorServiceProvider())
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Locator service uses transport layer to search
+for peers and to collect and maintain up-to-date
+data about peer's attributes.
+"""
+
+import threading, time, socket, cStringIO
+from tcf.services import locator
+from tcf.util import logging
+from tcf.channel import fromJSONSequence, toJSONSequence
+from tcf.channel.ChannelProxy import ChannelProxy
+from tcf import protocol, services, channel, peer, errors
+
+# Flag indicating whether tracing of the the discovery activity is enabled.
+__TRACE_DISCOVERY__ = False
+
+class SubNet(object):
+ def __init__(self, prefix_length, address, broadcast):
+ self.prefix_length = prefix_length
+ self.address = address
+ self.broadcast = broadcast
+ self.last_slaves_req_time = 0
+ def contains(self, addr):
+ if addr is None or self.address is None: return False
+ a1 = addr.getAddress()
+ a2 = self.address.getAddress()
+ if len(a1) != len(a2): return False
+ i = 0
+ if self.prefix_length <= len(a1) * 8:
+ l = self.prefix_length
+ else:
+ l = len(a1) * 8
+ while i + 8 <= l:
+ n = i / 8
+ if a1[n] != a2[n]: return False
+ i += 8
+ while i < l:
+ n = i / 8
+ m = 1 << (7 - i % 8)
+ if (a1[n] & m) != (a2[n] & m): return False
+ i += 1
+ return True
+ def __eq__(self, o):
+ if not isinstance(o, SubNet): return False
+ return self.prefix_length == o.prefix_length and \
+ self.broadcast == o.broadcast and \
+ self.address == o.address
+ def __hash__(self):
+ return hash(self.address)
+ def __str__(self):
+ return "%s/%d" % (self.address.getHostAddress(), self.prefix_length)
+
+class Slave(object):
+ # Time of last packet receiver from self slave
+ last_packet_time = 0
+ #Time of last REQ_SLAVES packet received from self slave
+ last_req_slaves_time = 0
+
+ def __init__(self, address, port):
+ self.address = address
+ self.port = port
+ def __str__(self):
+ return "%s/%d" % (self.address.getHostAddress(), self.port)
+
+class AddressCacheItem(object):
+ address = None
+ time_stamp = 0
+ used = False
+ def __init__(self, host):
+ self.host = host
+
+class InetAddress(object):
+ "Mimicking Java InetAddress class"
+ def __init__(self, host, addr):
+ self.host = host
+ self.addr = addr
+ def getAddress(self):
+ return socket.inet_aton(self.addr)
+ def getHostAddress(self):
+ return self.addr
+ def __eq__(self, other):
+ if not isinstance(other, InetAddress): return False
+ return self.addr == other.addr
+ def __str__(self):
+ return "%s/%s" % (self.host or "", self.addr)
+
+class InputPacket(object):
+ "Wrapper for UDP packet data."
+ def __init__(self, data, addr, port):
+ self.data = data
+ self.addr = addr
+ self.port = port
+ def getLength(self):
+ return len(self.data)
+ def getData(self):
+ return self.data
+ def getPort(self):
+ return self.port
+ def getAddress(self):
+ return self.addr
+ def __str__(self):
+ return "[address=%s,port=%d,data=\"%s\"]" % (self.getAddress(), self.getPort(), self.data)
+
+DISCOVEY_PORT = 1534
+MAX_PACKET_SIZE = 9000 - 40 - 8
+PREF_PACKET_SIZE = 1500 - 40 - 8
+
+# TODO: research usage of DNS-SD (DNS Service Discovery) to discover TCF peers
+class LocatorService(locator.LocatorService):
+ locator = None
+ peers = {} # str->Peer
+ listeners = [] # list of LocatorListener
+ error_log = set() # set of str
+
+ addr_cache = {} # str->AddressCacheItem
+ addr_request = False
+ local_peer = None
+ last_master_packet_time = 0
+
+ @classmethod
+ def getLocalPeer(cls):
+ return cls.local_peer
+
+ @classmethod
+ def getListeners(cls):
+ return cls.listeners[:]
+
+ @classmethod
+ def startup(cls):
+ if cls.locator:
+ cls.locator._startup()
+
+ @classmethod
+ def shutdown(cls):
+ if cls.locator:
+ cls.locator._shutdown()
+
+ def __init__(self):
+ self._error_log_lock = threading.RLock()
+ self._alive = False
+ LocatorService.locator = self
+ LocatorService.local_peer = peer.LocalPeer()
+
+ def _startup(self):
+ if self._alive: return
+ self._alive = True
+ self._addr_cache_lock = threading.Condition()
+ self.subnets = set()
+ self.slaves = []
+ self.inp_buf = bytearray(MAX_PACKET_SIZE)
+ self.out_buf = bytearray(MAX_PACKET_SIZE)
+ service = self
+ class TimerThread(threading.Thread):
+ def __init__(self, callable):
+ self._callable = callable
+ super(TimerThread, self).__init__()
+ def run(self):
+ while service._alive:
+ try:
+ time.sleep(locator.DATA_RETENTION_PERIOD / 4 / 1000.)
+ protocol.invokeAndWait(self._callable)
+ except RuntimeError:
+ # TCF event dispatch is shut down
+ return
+ except Exception as x:
+ service._log("Unhandled exception in TCF discovery timer thread", x)
+ self.timer_thread = TimerThread(self.__refresh_timer)
+ class DNSLookupThread(threading.Thread):
+ def run(self):
+ while service._alive:
+ try:
+ itemSet = None
+ with service._addr_cache_lock:
+ if not LocatorService.addr_request:
+ service._addr_cache_lock.wait(locator.DATA_RETENTION_PERIOD)
+ msec = int(time.time() * 1000)
+ for host, a in LocatorService.addr_cache.items():
+ if a.time_stamp + locator.DATA_RETENTION_PERIOD * 10 < msec:
+ if a.used:
+ if itemSet is None: itemSet = set()
+ itemSet.add(a)
+ else:
+ del LocatorService.addr_cache[host]
+ LocatorService.addr_request = False
+ if itemSet is not None:
+ for a in itemSet:
+ addr = None
+ try:
+ addr = socket.gethostbyname(a.host)
+ except socket.gaierror:
+ pass
+ with service._addr_cache_lock:
+ if addr is None:
+ a.address = None
+ else:
+ a.address = InetAddress(a.host, addr)
+ a.time_stamp = msec
+ a.used = False
+ except Exception as x:
+ service._log("Unhandled exception in TCF discovery DNS lookup thread", x)
+ self.dns_lookup_thread = DNSLookupThread()
+ class InputThread(threading.Thread):
+ def __init__(self, callable):
+ self._callable = callable
+ super(InputThread, self).__init__()
+ def run(self):
+ try:
+ while service._alive:
+ sock = service.socket
+ try:
+ data, addr = sock.recvfrom(MAX_PACKET_SIZE)
+ p = InputPacket(data, InetAddress(None, addr[0]), addr[1])
+ protocol.invokeAndWait(self._callable, p)
+ except RuntimeError:
+ # TCF event dispatch is shutdown
+ return
+ except socket.error as x:
+ if sock != service.socket: continue
+ # frequent error on windows, unknown reason
+ if x.errno == 10054: continue
+ port = sock.getsockname()[1]
+ service._log("Cannot read from datagram socket at port %d" % port, x)
+ time.sleep(2)
+ except Exception as x:
+ service._log("Unhandled exception in socket reading thread", x)
+ self.input_thread = InputThread(self.__handleDatagramPacket)
+ try:
+ self.loopback_addr = InetAddress(None, "127.0.0.1")
+ self.out_buf[0:8] = 'TCF%s\0\0\0\0' % locator.CONF_VERSION
+ self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ try:
+ self.socket.bind(('', DISCOVEY_PORT))
+ if __TRACE_DISCOVERY__:
+ logging.trace("Became the master agent (bound to port %d)" % self.socket.getsockname()[1])
+ except socket.error as x:
+ self.socket.bind(('', 0))
+ if __TRACE_DISCOVERY__:
+ logging.trace("Became a slave agent (bound to port %d)" % self.socket.getsockname()[1])
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
+ self.input_thread.setName("TCF Locator Receiver")
+ self.timer_thread.setName("TCF Locator Timer")
+ self.dns_lookup_thread.setName("TCF Locator DNS Lookup")
+ self.input_thread.setDaemon(True)
+ self.timer_thread.setDaemon(True)
+ self.dns_lookup_thread.setDaemon(True)
+ self.input_thread.start()
+ self.timer_thread.start()
+ self.dns_lookup_thread.start()
+ class LocatorListener(locator.LocatorListener):
+ def peerAdded(self, peer):
+ service._sendPeerInfo(peer, None, 0)
+ def peerChanged(self, peer):
+ service._sendPeerInfo(peer, None, 0)
+ self.listeners.append(LocatorListener())
+ self.__refreshSubNetList()
+ self.__sendPeersRequest(None, 0)
+ self.__sendAll(None, 0, None, int(time.time() * 1000))
+ except Exception as x:
+ self._log("Cannot open UDP socket for TCF discovery protocol", x)
+
+ def _shutdown(self):
+ if self._alive:
+ self._alive = False
+
+ def __makeErrorReport(self, code, msg):
+ err = {}
+ err[errors.ERROR_TIME] = int(time.time() * 1000)
+ err[errors.ERROR_CODE] = code
+ err[errors.ERROR_FORMAT] = msg
+ return err
+
+ def __command(self, channel, token, name, data):
+ try:
+ if name == "redirect":
+ peer_id = fromJSONSequence(data)[0]
+ _peer = self.peers.get(peer_id)
+ if _peer is None:
+ error = self.__makeErrorReport(errors.TCF_ERROR_UNKNOWN_PEER, "Unknown peer ID")
+ channel.sendResult(token, toJSONSequence((error,)))
+ return
+ channel.sendResult(token, toJSONSequence((None,)))
+ if isinstance(_peer, peer.LocalPeer):
+ channel.sendEvent(protocol.getLocator(), "Hello", toJSONSequence((channel.getLocalServices(),)))
+ return
+ ChannelProxy(channel, _peer.openChannel())
+ elif name == "sync":
+ channel.sendResult(token, None)
+ elif name == "getPeers":
+ arr = []
+ for p in self.peers.values():
+ arr.append(p.getAttributes())
+ channel.sendResult(token, toJSONSequence((None, arr)))
+ else:
+ channel.rejectCommand(token)
+ except Exception as x:
+ channel.terminate(x)
+
+ def _log(self, msg, x):
+ if not self._alive: return
+ # Don't report same error multiple times to avoid filling up the log file.
+ with self._error_log_lock:
+ if msg in self.error_log: return
+ self.error_log.add(msg)
+ protocol.log(msg, x)
+
+ def __getInetAddress(self, host):
+ if not host: return None
+ with self._addr_cache_lock:
+ i = self.addr_cache.get(host)
+ if i is None:
+ i = AddressCacheItem(host)
+ ch = host[0]
+ if ch == '[' or ch == ':' or ch >= '0' and ch <= '9':
+ try:
+ addr = socket.gethostbyname(host)
+ i.address = InetAddress(host, addr)
+ except socket.gaierror:
+ pass
+ i.time_stamp = int(time.time() * 1000)
+ else:
+ # socket.gethostbyname() can cause long delay - delegate to background thread
+ LocatorService.addr_request = True
+ self._addr_cache_lock.notify()
+ self.addr_cache[host] = i
+ i.used = True
+ return i.address
+
+ def __refresh_timer(self):
+ tm = int(time.time() * 1000)
+ # Cleanup slave table
+ if self.slaves:
+ i = 0
+ while i < len(self.slaves):
+ s = self.slaves[i]
+ if s.last_packet_time + locator.DATA_RETENTION_PERIOD < tm:
+ del self.slaves[i]
+ else:
+ i += 1
+
+ # Cleanup peers table
+ stale_peers = None
+ for p in self.peers.values():
+ if isinstance(p, peer.RemotePeer):
+ if p.getLastUpdateTime() + locator.DATA_RETENTION_PERIOD < tm:
+ if stale_peers == None: stale_peers = []
+ stale_peers.append(p)
+ if stale_peers is not None:
+ for p in stale_peers: p.dispose()
+
+ # Try to become a master
+ port = self.socket.getsockname()[1]
+ if port != DISCOVEY_PORT and \
+ self.last_master_packet_time + locator.DATA_RETENTION_PERIOD / 2 <= tm:
+ s0 = self.socket
+ s1 = None
+ try:
+ s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ s1.bind(DISCOVEY_PORT)
+ s1.setsockopt(socket.SOL_UDP, socket.SO_BROADCAST, 1)
+ self.socket = s1
+ s0.close()
+ except:
+ pass
+ self.__refreshSubNetList()
+ if port != DISCOVEY_PORT:
+ for subnet in self.subnets:
+ self.__addSlave(subnet.address, port, tm, tm)
+ self.__sendAll(None, 0, None, tm)
+
+ def __addSlave(self, addr, port, timestamp, time_now):
+ for s in self.slaves:
+ if s.port == port and s.address == addr:
+ if s.last_packet_time < timestamp: s.last_packet_time = timestamp
+ return s
+ s = Slave(addr, port)
+ s.last_packet_time = timestamp
+ self.slaves.append(s)
+ self.__sendPeersRequest(addr, port)
+ self.__sendAll(addr, port, s, time_now)
+ self.__sendSlaveInfo(s, time_now)
+ return s
+
+ def __refreshSubNetList(self):
+ subNetSet = set()
+ try:
+ self.__getSubNetList(subNetSet)
+ except Exception as x:
+ self._log("Cannot get list of network interfaces", x)
+ for s in tuple(self.subnets):
+ if s in subNetSet: continue
+ self.subnets.remove(s)
+ for s in subNetSet:
+ if s in self.subnets: continue
+ self.subnets.add(s)
+ if __TRACE_DISCOVERY__:
+ str = cStringIO.StringIO()
+ str.write("Refreshed subnet list:")
+ for subnet in self.subnets:
+ str.write("\n\t* address=%s, broadcast=%s" % (subnet.address, subnet.broadcast))
+ logging.trace(str.getvalue())
+
+ def __getSubNetList(self, set):
+ # TODO iterate over network interfaces to get proper broadcast addresses
+ hostname = socket.gethostname()
+ _, _, addresses = socket.gethostbyname_ex(hostname)
+ if not "127.0.0.1" in addresses:
+ addresses.append("127.0.0.1")
+ for address in addresses:
+ rawaddr = socket.inet_aton(address)
+ if len(rawaddr) != 4: continue
+ rawaddr = rawaddr[:3] + '\xFF'
+ broadcast = socket.inet_ntoa(rawaddr)
+ set.add(SubNet(24, InetAddress(hostname, address), InetAddress(None, broadcast)))
+
+ def __getUTF8Bytes(self, s):
+ return s.encode("UTF-8")
+
+ # Used for tracing
+ packetTypes = [
+ None,
+ "CONF_REQ_INFO",
+ "CONF_PEER_INFO",
+ "CONF_REQ_SLAVES",
+ "CONF_SLAVES_INFO",
+ "CONF_PEERS_REMOVED"
+ ]
+
+ def __sendDatagramPacket(self, subnet, size, addr, port):
+ try:
+ if addr is None:
+ addr = subnet.broadcast
+ port = DISCOVEY_PORT
+ for slave in self.slaves:
+ self.__sendDatagramPacket(subnet, size, slave.address, slave.port)
+ if not subnet.contains(addr): return False
+ if port == self.socket.getsockname()[1] and addr == subnet.address: return False
+ self.socket.sendto(str(self.out_buf[:size]), (addr.getHostAddress(), port))
+
+ if __TRACE_DISCOVERY__:
+ map = None
+ if self.out_buf[4] == locator.CONF_PEER_INFO:
+ map = self.__parsePeerAttributes(self.out_buf, 8)
+ elif self.out_buf[4] == locator.CONF_SLAVES_INFO:
+ map = self.__parseIDs(self.out_buf, size)
+ elif self.out_buf[4] == locator.CONF_PEERS_REMOVED:
+ map = self.__parseIDs(self.out_buf, size)
+ self.__traceDiscoveryPacket(False, self.packetTypes[self.out_buf[4]], map, addr, port)
+ except Exception as x:
+ self._log("Cannot send datagram packet to %s" % addr, x)
+ return False
+ return True
+
+ def __parsePeerAttributes(self, data, size):
+ """
+ Parse peer attributes in CONF_PEER_INFO packet data
+
+ @param data - the packet data
+ @param size - the packet size
+ @return a map containing the attributes
+ """
+ map = {}
+ s = data[8:size - 8].decode("UTF-8")
+ l = len(s)
+ i = 0
+ while i < l:
+ i0 = i
+ while i < l and s[i] != '=' and s[i] != '\0': i += 1
+ i1 = i
+ if i < l and s[i] == '=': i += 1
+ i2 = i
+ while i < l and s[i] != '\0': i += 1
+ i3 = i
+ if i < l and s[i] == '\0': i += 1
+ key = s[i0:i1]
+ val = s[i2:i3]
+ map[key] = val
+ return map
+
+ def __parseIDs(self, data, size):
+ """
+ Parse list of IDs in CONF_SLAVES_INFO and CONF_PEERS_REMOVED packet data.
+
+ @param data - the packet data
+ @param size - the packet size
+ @return a map containing the IDs
+ """
+ cnt = 0
+ map = {}
+ s = data[8:size - 8].decode("UTF-8")
+ l = len(s)
+ i = 0
+ while i < l:
+ i0 = i
+ while i < l and s[i] != '\0': i += 1
+ if i > i0:
+ id = s[i0:i]
+ map[str(cnt)] = id
+ cnt += 1
+ while i < l and s[i] == '\0': i += 1
+ return map
+
+ def __sendPeersRequest(self, addr, port):
+ self.out_buf[4] = locator.CONF_REQ_INFO
+ for subnet in self.subnets:
+ self.__sendDatagramPacket(subnet, 8, addr, port)
+
+ def _sendPeerInfo(self, _peer, addr, port):
+ attrs = _peer.getAttributes()
+ peer_addr = self.__getInetAddress(attrs.get(peer.ATTR_IP_HOST))
+ if peer_addr is None: return
+ if attrs.get(peer.ATTR_IP_PORT) is None: return
+ self.out_buf[4] = locator.CONF_PEER_INFO
+ i = 8
+
+ for subnet in self.subnets:
+ if isinstance(_peer, peer.RemotePeer):
+ if self.socket.getsockname()[1] != DISCOVEY_PORT: return
+ if not subnet.address == self.loopback_addr and not subnet.address == peer_addr: continue
+ if not subnet.address == self.loopback_addr:
+ if not subnet.contains(peer_addr): continue
+ if i == 8:
+ sb = cStringIO.StringIO()
+ for key in attrs.keys():
+ sb.write(key)
+ sb.write('=')
+ sb.write(attrs.get(key))
+ sb.write('\0')
+ bt = self.__getUTF8Bytes(sb.getvalue())
+ if i + len(bt) > len(self.out_buf): return
+ self.out_buf[i:i+len(bt)] = bt
+ i += len(bt)
+ if self.__sendDatagramPacket(subnet, i, addr, port): subnet.send_all_ok = True
+
+ def __sendEmptyPacket(self, addr, port):
+ self.out_buf[4] = locator.CONF_SLAVES_INFO
+ for subnet in self.subnets:
+ if subnet.send_all_ok: continue
+ self.__sendDatagramPacket(subnet, 8, addr, port)
+
+ def __sendAll(self, addr, port, sl, tm):
+ for subnet in self.subnets: subnet.send_all_ok = False
+ for peer in self.peers.values(): self._sendPeerInfo(peer, addr, port)
+ if addr is not None and sl is not None and sl.last_req_slaves_time + locator.DATA_RETENTION_PERIOD >= tm:
+ self.__sendSlavesInfo(addr, port, tm)
+ self.__sendEmptyPacket(addr, port)
+
+ def __sendSlavesRequest(self, subnet, addr, port):
+ self.out_buf[4] = locator.CONF_REQ_SLAVES
+ self.__sendDatagramPacket(subnet, 8, addr, port)
+
+ def __sendSlaveInfo(self, x, tm):
+ ttl = x.last_packet_time + locator.DATA_RETENTION_PERIOD - tm
+ if ttl <= 0: return
+ self.out_buf[4] = locator.CONF_SLAVES_INFO
+ for subnet in self.subnets:
+ if not subnet.contains(x.address): continue
+ i = 8
+ s = "%d:%s:%s" % (ttl, x.port, x.address.getHostAddress())
+ bt = self.__getUTF8Bytes(s)
+ self.out_buf[i:i+len(bt)] = bt
+ i += len(bt)
+ self.out_buf[i] = 0
+ i += 1
+ for y in self.slaves:
+ if not subnet.contains(y.address): continue
+ if y.last_req_slaves_time + locator.DATA_RETENTION_PERIOD < tm: continue
+ self.__sendDatagramPacket(subnet, i, y.address, y.port)
+
+ def __sendSlavesInfo(self, addr, port, tm):
+ self.out_buf[4] = locator.CONF_SLAVES_INFO
+ for subnet in self.subnets:
+ if not subnet.contains(addr): continue
+ i = 8
+ for x in self.slaves:
+ ttl = x.last_packet_time + locator.DATA_RETENTION_PERIOD - tm
+ if ttl <= 0: return
+ if x.port == port and x.address == addr: continue
+ if not subnet.address == self.loopback_addr:
+ if not subnet.contains(x.address): continue
+ subnet.send_all_ok = True
+ s = "%d:%s:%s" % (x.last_packet_time, x.port, x.address.getHostAddress())
+ bt = self.__getUTF8Bytes(s)
+ if i > 8 and i + len(bt) >= PREF_PACKET_SIZE:
+ self.__sendDatagramPacket(subnet, i, addr, port)
+ i = 8
+ self.out_buf[i:len(bt)] = bt
+ i += len(bt)
+ self.out_buf[i] = 0
+ i += 1
+ if i > 8: self.__sendDatagramPacket(subnet, i, addr, port)
+
+ def __isRemote(self, address, port):
+ if port != self.socket.getsockname()[1]: return True
+ for s in self.subnets:
+ if s.address == address: return False
+ return True
+
+ def __handleDatagramPacket(self, p):
+ try:
+ tm = int(time.time() * 1000)
+ buf = p.getData()
+ len = p.getLength()
+ if len < 8: return
+ if buf[0] != 'T': return
+ if buf[1] != 'C': return
+ if buf[2] != 'F': return
+ if buf[3] != locator.CONF_VERSION: return
+ remote_port = p.getPort()
+ remote_address = p.getAddress()
+ if self.__isRemote(remote_address, remote_port):
+ if buf[4] == locator.CONF_PEERS_REMOVED:
+ self.__handlePeerRemovedPacket(p)
+ else:
+ sl = None
+ if remote_port != DISCOVEY_PORT:
+ sl = self.__addSlave(remote_address, remote_port, tm, tm)
+ code = ord(buf[4])
+ if code == locator.CONF_PEER_INFO:
+ self.__handlePeerInfoPacket(p)
+ elif code == locator.CONF_REQ_INFO:
+ self.__handleReqInfoPacket(p, sl, tm)
+ elif code == locator.CONF_SLAVES_INFO:
+ self.__handleSlavesInfoPacket(p, tm)
+ elif code == locator.CONF_REQ_SLAVES:
+ self.__handleReqSlavesPacket(p, sl, tm)
+ for subnet in self.subnets:
+ if not subnet.contains(remote_address): continue
+ delay = locator.DATA_RETENTION_PERIOD / 3
+ if remote_port != DISCOVEY_PORT: delay = locator.DATA_RETENTION_PERIOD / 32
+ elif subnet.address != remote_address: delay = locator.DATA_RETENTION_PERIOD / 2
+ if subnet.last_slaves_req_time + delay <= tm:
+ self.__sendSlavesRequest(subnet, remote_address, remote_port)
+ subnet.last_slaves_req_time = tm
+ if subnet.address == remote_address and remote_port == DISCOVEY_PORT:
+ self.last_master_packet_time = tm
+ except Exception as x:
+ self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
+
+ def __handlePeerInfoPacket(self, p):
+ try:
+ map = self.__parsePeerAttributes(p.getData(), p.getLength())
+ if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_PEER_INFO", map, p)
+ id = map.get(peer.ATTR_ID)
+ if id is None: raise RuntimeError("Invalid peer info: no ID")
+ ok = True
+ host = map.get(peer.ATTR_IP_HOST)
+ if host is not None:
+ ok = False
+ peer_addr = self.__getInetAddress(host)
+ if peer_addr is not None:
+ for subnet in self.subnets:
+ if subnet.contains(peer_addr):
+ ok = True
+ break
+ if ok:
+ _peer = self.peers.get(id)
+ if isinstance(_peer, peer.RemotePeer):
+ _peer.updateAttributes(map)
+ elif _peer is None:
+ peer.RemotePeer(map)
+ except Exception as x:
+ self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
+
+ def __handleReqInfoPacket(self, p, sl, tm):
+ if __TRACE_DISCOVERY__:
+ self.__traceDiscoveryPacket(True, "CONF_REQ_INFO", None, p)
+ self.__sendAll(p.getAddress(), p.getPort(), sl, tm)
+
+ def __handleSlavesInfoPacket(self, p, time_now):
+ try:
+ map = self.__parseIDs(p.getData(), p.getLength())
+ if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_SLAVES_INFO", map, p)
+ for s in map.values():
+ i = 0
+ l = len(s)
+ time0 = i
+ while i < l and s[i] != ':' and s[i] != '\0': i += 1
+ time1 = i
+ if i < l and s[i] == ':': i += 1
+ port0 = i
+ while i < l and s[i] != ':' and s[i] != '\0': i += 1
+ port1 = i
+ if i < l and s[i] == ':': i += 1
+ host0 = i
+ while i < l and s[i] != '\0': i += 1
+ host1 = i
+ port = int(s[port0:port1])
+ timestamp = s[time0:time1]
+ host = s[host0:host1]
+ if port != DISCOVEY_PORT:
+ addr = self.__getInetAddress(host)
+ if addr is not None:
+ delta = 10006030 # 30 minutes
+ if len(timestamp) > 0:
+ time_val = int(timestamp)
+ else:
+ time_val = time_now
+ if time_val < 3600000:
+ # Time stamp is "time to live" in milliseconds
+ time_val = time_now + time_val / 1000 - locator.DATA_RETENTION_PERIOD
+ elif time_val < time_now / 1000 + 50000000:
+ # Time stamp is in seconds
+ time_val= 1000
+ else:
+ # Time stamp is in milliseconds
+ pass
+ if time_val < time_now - delta or time_val > time_now + delta:
+ msg = "Invalid slave info timestamp: %s -> %s" % (
+ timestamp, time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time_val/1000.)))
+ self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), Exception(msg))
+ time_val = time_now - locator.DATA_RETENTION_PERIOD / 2
+ self.__addSlave(addr, port, time_val, time_now)
+ except Exception as x:
+ self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
+
+ def __handleReqSlavesPacket(self, p, sl, tm):
+ if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_REQ_SLAVES", None, p)
+ if sl is not None: sl.last_req_slaves_time = tm
+ self.__sendSlavesInfo(p.getAddress(), p.getPort(), tm)
+
+ def __handlePeerRemovedPacket(self, p):
+ try:
+ map = self.__parseIDs(p.getData(), p.getLength())
+ if __TRACE_DISCOVERY__: self.__traceDiscoveryPacket(True, "CONF_PEERS_REMOVED", map, p)
+ for id in map.values():
+ _peer = self.peers.get(id)
+ if isinstance(_peer, peer.RemotePeer): _peer.dispose()
+ except Exception as x:
+ self._log("Invalid datagram packet received from %s/%s" % (p.getAddress(), p.getPort()), x)
+
+
+ @classmethod
+ def getLocator(cls):
+ return cls.locator
+
+ def getPeers(self):
+ assert protocol.isDispatchThread()
+ return self.peers
+
+ def redirect(self, peer, done):
+ raise RuntimeError("Channel redirect cannot be done on local peer")
+
+ def sync(self, done):
+ raise RuntimeError("Channel sync cannot be done on local peer")
+
+ def addListener(self, listener):
+ assert listener is not None
+ assert protocol.isDispatchThread()
+ self.listeners.append(listener)
+
+ def removeListener(self, listener):
+ assert protocol.isDispatchThread()
+ self.listeners.remove(listener)
+
+ @classmethod
+ def __traceDiscoveryPacket(cls, received, type, attrs, addr, port=None):
+ """
+ Log that a TCF Discovery packet has be sent or received. The trace is
+ sent to stdout. This should be called only if the tracing has been turned
+ on.
+
+ @param received
+ True if the packet was sent, otherwise it was received
+ @param type
+ a string specifying the type of packet, e.g., "CONF_PEER_INFO"
+ @param attrs
+ a set of attributes relevant to the type of packet (typically
+ a peer's attributes)
+ @param addr
+ the network address the packet is being sent to
+ @param port
+ the port the packet is being sent to
+ """
+ assert __TRACE_DISCOVERY__
+ if port is None:
+ # addr is a InputPacket
+ port = addr.getPort()
+ addr = addr.getAddress()
+ str = cStringIO.StringIO()
+ str.write(type)
+ str.write((" sent to ", " received from ")[received])
+ str.write("%s/%s" % (addr, port))
+ if attrs is not None:
+ for key, value in attrs.items():
+ str.write("\n\t%s=%s" % (key, value))
+ logging.trace(str.getvalue())
+
+class LocatorServiceProvider(services.ServiceProvider):
+ def getLocalService(self, _channel):
+ class CommandServer(channel.CommandServer):
+ def command(self, token, name, data):
+ LocatorService.locator.command(channel, token, name, data)
+ _channel.addCommandServer(LocatorService.locator, CommandServer())
+ return (LocatorService.locator,)
+
+services.addServiceProvider(LocatorServiceProvider())
diff --git a/python/src/tcf/services/local/__init__.py b/python/src/tcf/services/local/__init__.py
index cf36110a7..29aa42bc1 100644
--- a/python/src/tcf/services/local/__init__.py
+++ b/python/src/tcf/services/local/__init__.py
@@ -1,10 +1,10 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
diff --git a/python/src/tcf/services/locator.py b/python/src/tcf/services/locator.py
index 10199a140..51006cba1 100644
--- a/python/src/tcf/services/locator.py
+++ b/python/src/tcf/services/locator.py
@@ -1,94 +1,94 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Locator service uses transport layer to search for peers and to collect data about
-peer's attributes and capabilities (services). Discovery mechanism depends on transport protocol
-and is part of that protocol handler. Targets, known to other hosts, can be found through
-remote instances of Locator service. Automatically discovered targets require no further
-configuration. Additional targets can be configured manually.
-
-Clients should use protocol.getLocator() to obtain local instance of locator,
-then locator.getPeers() can be used to get list of available peers (hosts and targets).
-"""
-
-from tcf import services
-
-# Peer data retention period in milliseconds.
-DATA_RETENTION_PERIOD = 60 * 1000;
-
-# Auto-configuration protocol version.
-CONF_VERSION = '2'
-
-# Auto-configuration command and response codes.
-CONF_REQ_INFO = 1
-CONF_PEER_INFO = 2
-CONF_REQ_SLAVES = 3
-CONF_SLAVES_INFO = 4
-CONF_PEERS_REMOVED = 5
-
-NAME = "Locator"
-
-class LocatorService(services.Service):
- def getName(self):
- return NAME
- def getPeers(self):
- """
- Get map (ID -> IPeer) of available peers (hosts and targets).
- The method return cached (currently known to the framework) list of peers.
- The list is updated according to event received from transport layer
- """
- raise NotImplementedError("Abstract method")
- def redirect(self, peer, done):
- """
- Redirect this service channel to given peer using this service as a proxy.
- @param peer - Peer ID or attributes map.
- """
- raise NotImplementedError("Abstract method")
- def sync(self, done):
- """
- Call back after TCF messages sent to this target up to this moment are delivered.
- This method is intended for synchronization of messages
- across multiple channels.
-
- Note: Cross channel synchronization can reduce performance and throughput.
- Most clients don't need channel synchronization and should not call this method.
-
- @param done will be executed by dispatch thread after communication
- messages are delivered to corresponding targets.
-
- This is internal API, TCF clients should use module 'tcf.protocol'.
- """
- raise NotImplementedError("Abstract method")
- def addListener(self, listener):
- "Add a listener for Locator service events."
- raise NotImplementedError("Abstract method")
- def removeListener(self, listener):
- "Remove a listener for Locator service events."
- raise NotImplementedError("Abstract method")
-
-class DoneRedirect(object):
- def doneRedirect(self, token, error):
- pass
-
-class DoneSync(object):
- def doneSync(self, token):
- pass
-
-class LocatorListener(object):
- def peerAdded(self, peer):
- pass
- def peerChanged(self, peer):
- pass
- def peerRemoved(self, id):
- pass
- def peerHeartBeat(self, id):
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Locator service uses transport layer to search for peers and to collect data about
+peer's attributes and capabilities (services). Discovery mechanism depends on transport protocol
+and is part of that protocol handler. Targets, known to other hosts, can be found through
+remote instances of Locator service. Automatically discovered targets require no further
+configuration. Additional targets can be configured manually.
+
+Clients should use protocol.getLocator() to obtain local instance of locator,
+then locator.getPeers() can be used to get list of available peers (hosts and targets).
+"""
+
+from tcf import services
+
+# Peer data retention period in milliseconds.
+DATA_RETENTION_PERIOD = 60 * 1000;
+
+# Auto-configuration protocol version.
+CONF_VERSION = '2'
+
+# Auto-configuration command and response codes.
+CONF_REQ_INFO = 1
+CONF_PEER_INFO = 2
+CONF_REQ_SLAVES = 3
+CONF_SLAVES_INFO = 4
+CONF_PEERS_REMOVED = 5
+
+NAME = "Locator"
+
+class LocatorService(services.Service):
+ def getName(self):
+ return NAME
+ def getPeers(self):
+ """
+ Get map (ID -> IPeer) of available peers (hosts and targets).
+ The method return cached (currently known to the framework) list of peers.
+ The list is updated according to event received from transport layer
+ """
+ raise NotImplementedError("Abstract method")
+ def redirect(self, peer, done):
+ """
+ Redirect this service channel to given peer using this service as a proxy.
+ @param peer - Peer ID or attributes map.
+ """
+ raise NotImplementedError("Abstract method")
+ def sync(self, done):
+ """
+ Call back after TCF messages sent to this target up to this moment are delivered.
+ This method is intended for synchronization of messages
+ across multiple channels.
+
+ Note: Cross channel synchronization can reduce performance and throughput.
+ Most clients don't need channel synchronization and should not call this method.
+
+ @param done will be executed by dispatch thread after communication
+ messages are delivered to corresponding targets.
+
+ This is internal API, TCF clients should use module 'tcf.protocol'.
+ """
+ raise NotImplementedError("Abstract method")
+ def addListener(self, listener):
+ "Add a listener for Locator service events."
+ raise NotImplementedError("Abstract method")
+ def removeListener(self, listener):
+ "Remove a listener for Locator service events."
+ raise NotImplementedError("Abstract method")
+
+class DoneRedirect(object):
+ def doneRedirect(self, token, error):
+ pass
+
+class DoneSync(object):
+ def doneSync(self, token):
+ pass
+
+class LocatorListener(object):
+ def peerAdded(self, peer):
+ pass
+ def peerChanged(self, peer):
+ pass
+ def peerRemoved(self, id):
+ pass
+ def peerHeartBeat(self, id):
+ pass
diff --git a/python/src/tcf/services/memory.py b/python/src/tcf/services/memory.py
index de97b2026..40a0c007a 100644
--- a/python/src/tcf/services/memory.py
+++ b/python/src/tcf/services/memory.py
@@ -1,303 +1,303 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Memory service provides basic operations to read/write memory on a target.
-"""
-
-from tcf import services
-
-NAME = "Memory"
-
-# Context property names.
-PROP_ID = "ID" # String, ID of the context, same as getContext command argument
-PROP_PARENT_ID = "ParentID" # String, ID of a parent context
-PROP_PROCESS_ID = "ProcessID" # String, process ID, see Processes service
-PROP_BIG_ENDIAN = "BigEndian" # Boolean, True if memory is big-endian
-PROP_ADDRESS_SIZE = "AddressSize" # Number, size of memory address in bytes
-PROP_NAME = "Name" # String, name of the context, can be used for UI purposes
-PROP_START_BOUND = "StartBound" # Number, lowest address (inclusive) which is valid for the context
-PROP_END_BOUND = "EndBound" # Number, highest address (inclusive) which is valid for the context
-PROP_ACCESS_TYPES = "AccessTypes" # Array of String, the access types allowed for this context
-
-# Values of "AccessTypes".
-# Target system can support multiple different memory access types, like instruction and data access.
-# Different access types can use different logic for address translation and memory mapping, so they can
-# end up accessing different data bits, even if address is the same.
-# Each distinct access type should be represented by separate memory context.
-# A memory context can represent multiple access types if they are equivalent - all access same memory bits.
-# Same data bits can be exposed through multiple memory contexts.
-ACCESS_INSTRUCTION = "instruction" # Context represent instructions fetch access
-ACCESS_DATA = "data" # Context represents data access
-ACCESS_IO = "io" # Context represents IO peripherals
-ACCESS_USER = "user" # Context represents a user (e.g. application running in Linux) view to memory
-ACCESS_SUPERVISOR = "supervisor" # Context represents a supervisor (e.g. Linux kernel) view to memory
-ACCESS_HYPERVISOR = "hypervisor" # Context represents a hypervisor view to memory
-ACCESS_VIRTUAL = "virtual" # Context uses virtual addresses
-ACCESS_PHYSICAL = "physical" # Context uses physical addresses
-ACCESS_CACHE = "cache" # Context is a cache
-ACCESS_TLB = "tlb" # Context is a TLB memory
-
-
-# Memory access mode:
-# Carry on when some of the memory cannot be accessed and
-# return MemoryError at the end if any of the bytes
-# were not processed correctly.
-MODE_CONTINUEONERROR = 0x1
-
-# Memory access mode:
-# Verify result of memory operations (by reading and comparing).
-MODE_VERIFY = 0x2
-
-class MemoryContext(object):
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Memory Context %s]" % self._props
-
- def getProperties(self):
- """
- Get context properties. See PROP_* definitions for property names.
- Context properties are read only, clients should not try to modify them.
- @return Map of context properties.
- """
- return self._props
-
- def getID(self):
- """
- Retrieve context ID.
- Same as getProperties().get('ID')
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Retrieve parent context ID.
- Same as getProperties().get('ParentID')
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getProcessID(self):
- """
- Retrieve context process ID.
- Same as getProperties().get('ProcessID')
- """
- return self._props.get(PROP_PROCESS_ID)
-
- def isBigEndian(self):
- """
- Get memory endianness.
- @return True if memory is big-endian.
- """
- return self._props.get(PROP_BIG_ENDIAN, False)
-
- def getAddressSize(self):
- """
- Get memory address size.
- @return number of bytes used to store memory address value.
- """
- return self._props.get(PROP_ADDRESS_SIZE, 0)
-
- def getName(self):
- """
- Get memory context name.
- The name can be used for UI purposes.
- @return context name.
- """
- return self._props.get(PROP_NAME)
-
- def getStartBound(self):
- """
- Get lowest address (inclusive) which is valid for the context.
- @return lowest address.
- """
- return self._props.get(PROP_START_BOUND)
-
- def getEndBound(self):
- """
- Get highest address (inclusive) which is valid for the context.
- @return highest address.
- """
- return self._props.get(PROP_END_BOUND)
-
- def getAccessTypes(self):
- """
- Get the access types allowed for this context.
- @return collection of access type names.
- """
- return self._props.get(PROP_ACCESS_TYPES)
-
- def set(self, addr, word_size, buf, offs, size, mode, done):
- """
- Set target memory.
- If 'word_size' is 0 it means client does not care about word size.
- """
- raise NotImplementedError("Abstract method")
-
- def get(self, addr, word_size, buf, offs, size, mode, done):
- """
- Read target memory.
- """
- raise NotImplementedError("Abstract method")
-
- def fill(self, addr, word_size, value, size, mode, done):
- """
- Fill target memory with given pattern.
- 'size' is number of bytes to fill.
- """
- raise NotImplementedError("Abstract method")
-
-class DoneMemory(object):
- """
- Client call back interface for set(), get() and fill() commands.
- """
- def doneMemory(self, token, error):
- pass
-
-class MemoryError(Exception):
- pass
-
-class ErrorOffset(object):
- """
- ErrorOffset may be implemented by MemoryError object,
- which is returned by get, set and fill commands.
-
- get/set/fill () returns this exception when reading failed
- for some but not all bytes, and MODE_CONTINUEONERROR
- has been set in mode. (For example, when only part of the request
- translates to valid memory addresses.)
- Exception.getMessage can be used for generalized message of the
- possible reasons of partial memory operation.
- """
- # Error may have per byte information
- BYTE_VALID = 0x00
- BYTE_UNKNOWN = 0x01 # e.g. out of range
- BYTE_INVALID = 0x02
- BYTE_CANNOT_READ = 0x04
- BYTE_CANNOT_WRITE = 0x08
-
- RANGE_KEY_ADDR = "addr"
- RANGE_KEY_SIZE = "size"
- RANGE_KEY_STAT = "stat"
- RANGE_KEY_MSG = "msg"
-
- def getStatus(self, offset):
- raise NotImplementedError("Abstract method")
-
- def getMessage(self, offset):
- raise NotImplementedError("Abstract method")
-
-class MemoryService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context info for given context ID.
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve contexts available for memory commands.
- A context corresponds to an execution thread, process, address space, etc.
- A context can belong to a parent context. Contexts hierarchy can be simple
- plain list or it can form a tree. It is up to target agent developers to choose
- layout that is most descriptive for a given target. Context IDs are valid across
- all services. In other words, all services access same hierarchy of contexts,
- with same IDs, however, each service accesses its own subset of context's
- attributes and functionality, which is relevant to that service.
-
- @param parent_context_id - parent context ID. Can be None -
- to retrieve top level of the hierarchy, or one of context IDs retrieved
- by previous getChildren commands.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add memory service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove memory service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
-class MemoryListener(object):
- """
- Memory event listener is notified when memory context hierarchy
- changes, and when memory is modified by memory service commands.
- """
-
- def contextAdded(self, contexts):
- """
- Called when a new memory access context(s) is created.
- """
- pass
-
- def contextChanged(self, contexts):
- """
- Called when a memory access context(s) properties changed.
- """
- pass
-
- def contextRemoved(self, context_ids):
- """
- Called when memory access context(s) is removed.
- """
- pass
-
- def memoryChanged(self, context_id, addr, size):
- """
- Called when target memory content was changed and clients
- need to update themselves. Clients, at least, should invalidate
- corresponding cached memory data.
- Not every change is notified - it is not possible,
- only those, which are not caused by normal execution of the debuggee.
- 'addr' and 'size' can be None if unknown.
- """
- pass
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Memory service provides basic operations to read/write memory on a target.
+"""
+
+from tcf import services
+
+NAME = "Memory"
+
+# Context property names.
+PROP_ID = "ID" # String, ID of the context, same as getContext command argument
+PROP_PARENT_ID = "ParentID" # String, ID of a parent context
+PROP_PROCESS_ID = "ProcessID" # String, process ID, see Processes service
+PROP_BIG_ENDIAN = "BigEndian" # Boolean, True if memory is big-endian
+PROP_ADDRESS_SIZE = "AddressSize" # Number, size of memory address in bytes
+PROP_NAME = "Name" # String, name of the context, can be used for UI purposes
+PROP_START_BOUND = "StartBound" # Number, lowest address (inclusive) which is valid for the context
+PROP_END_BOUND = "EndBound" # Number, highest address (inclusive) which is valid for the context
+PROP_ACCESS_TYPES = "AccessTypes" # Array of String, the access types allowed for this context
+
+# Values of "AccessTypes".
+# Target system can support multiple different memory access types, like instruction and data access.
+# Different access types can use different logic for address translation and memory mapping, so they can
+# end up accessing different data bits, even if address is the same.
+# Each distinct access type should be represented by separate memory context.
+# A memory context can represent multiple access types if they are equivalent - all access same memory bits.
+# Same data bits can be exposed through multiple memory contexts.
+ACCESS_INSTRUCTION = "instruction" # Context represent instructions fetch access
+ACCESS_DATA = "data" # Context represents data access
+ACCESS_IO = "io" # Context represents IO peripherals
+ACCESS_USER = "user" # Context represents a user (e.g. application running in Linux) view to memory
+ACCESS_SUPERVISOR = "supervisor" # Context represents a supervisor (e.g. Linux kernel) view to memory
+ACCESS_HYPERVISOR = "hypervisor" # Context represents a hypervisor view to memory
+ACCESS_VIRTUAL = "virtual" # Context uses virtual addresses
+ACCESS_PHYSICAL = "physical" # Context uses physical addresses
+ACCESS_CACHE = "cache" # Context is a cache
+ACCESS_TLB = "tlb" # Context is a TLB memory
+
+
+# Memory access mode:
+# Carry on when some of the memory cannot be accessed and
+# return MemoryError at the end if any of the bytes
+# were not processed correctly.
+MODE_CONTINUEONERROR = 0x1
+
+# Memory access mode:
+# Verify result of memory operations (by reading and comparing).
+MODE_VERIFY = 0x2
+
+class MemoryContext(object):
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Memory Context %s]" % self._props
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Retrieve context ID.
+ Same as getProperties().get('ID')
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Retrieve parent context ID.
+ Same as getProperties().get('ParentID')
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getProcessID(self):
+ """
+ Retrieve context process ID.
+ Same as getProperties().get('ProcessID')
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def isBigEndian(self):
+ """
+ Get memory endianness.
+ @return True if memory is big-endian.
+ """
+ return self._props.get(PROP_BIG_ENDIAN, False)
+
+ def getAddressSize(self):
+ """
+ Get memory address size.
+ @return number of bytes used to store memory address value.
+ """
+ return self._props.get(PROP_ADDRESS_SIZE, 0)
+
+ def getName(self):
+ """
+ Get memory context name.
+ The name can be used for UI purposes.
+ @return context name.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getStartBound(self):
+ """
+ Get lowest address (inclusive) which is valid for the context.
+ @return lowest address.
+ """
+ return self._props.get(PROP_START_BOUND)
+
+ def getEndBound(self):
+ """
+ Get highest address (inclusive) which is valid for the context.
+ @return highest address.
+ """
+ return self._props.get(PROP_END_BOUND)
+
+ def getAccessTypes(self):
+ """
+ Get the access types allowed for this context.
+ @return collection of access type names.
+ """
+ return self._props.get(PROP_ACCESS_TYPES)
+
+ def set(self, addr, word_size, buf, offs, size, mode, done):
+ """
+ Set target memory.
+ If 'word_size' is 0 it means client does not care about word size.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def get(self, addr, word_size, buf, offs, size, mode, done):
+ """
+ Read target memory.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def fill(self, addr, word_size, value, size, mode, done):
+ """
+ Fill target memory with given pattern.
+ 'size' is number of bytes to fill.
+ """
+ raise NotImplementedError("Abstract method")
+
+class DoneMemory(object):
+ """
+ Client call back interface for set(), get() and fill() commands.
+ """
+ def doneMemory(self, token, error):
+ pass
+
+class MemoryError(Exception):
+ pass
+
+class ErrorOffset(object):
+ """
+ ErrorOffset may be implemented by MemoryError object,
+ which is returned by get, set and fill commands.
+
+ get/set/fill () returns this exception when reading failed
+ for some but not all bytes, and MODE_CONTINUEONERROR
+ has been set in mode. (For example, when only part of the request
+ translates to valid memory addresses.)
+ Exception.getMessage can be used for generalized message of the
+ possible reasons of partial memory operation.
+ """
+ # Error may have per byte information
+ BYTE_VALID = 0x00
+ BYTE_UNKNOWN = 0x01 # e.g. out of range
+ BYTE_INVALID = 0x02
+ BYTE_CANNOT_READ = 0x04
+ BYTE_CANNOT_WRITE = 0x08
+
+ RANGE_KEY_ADDR = "addr"
+ RANGE_KEY_SIZE = "size"
+ RANGE_KEY_STAT = "stat"
+ RANGE_KEY_MSG = "msg"
+
+ def getStatus(self, offset):
+ raise NotImplementedError("Abstract method")
+
+ def getMessage(self, offset):
+ raise NotImplementedError("Abstract method")
+
+class MemoryService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve contexts available for memory commands.
+ A context corresponds to an execution thread, process, address space, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getChildren commands.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add memory service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove memory service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+class MemoryListener(object):
+ """
+ Memory event listener is notified when memory context hierarchy
+ changes, and when memory is modified by memory service commands.
+ """
+
+ def contextAdded(self, contexts):
+ """
+ Called when a new memory access context(s) is created.
+ """
+ pass
+
+ def contextChanged(self, contexts):
+ """
+ Called when a memory access context(s) properties changed.
+ """
+ pass
+
+ def contextRemoved(self, context_ids):
+ """
+ Called when memory access context(s) is removed.
+ """
+ pass
+
+ def memoryChanged(self, context_id, addr, size):
+ """
+ Called when target memory content was changed and clients
+ need to update themselves. Clients, at least, should invalidate
+ corresponding cached memory data.
+ Not every change is notified - it is not possible,
+ only those, which are not caused by normal execution of the debuggee.
+ 'addr' and 'size' can be None if unknown.
+ """
+ pass
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
diff --git a/python/src/tcf/services/memorymap.py b/python/src/tcf/services/memorymap.py
index 4b805fe97..49c9d4b07 100644
--- a/python/src/tcf/services/memorymap.py
+++ b/python/src/tcf/services/memorymap.py
@@ -1,188 +1,188 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-MemoryMap service provides information about executable modules (files) mapped (loaded) into target memory.
-"""
-
-from tcf import services
-
-NAME = "MemoryMap"
-
-
-# Memory region property names.
-# Number, region address in memory
-PROP_ADDRESS = "Addr"
-
-# Number, region size
-PROP_SIZE = "Size"
-
-# Number, region offset in the file
-PROP_OFFSET = "Offs"
-
-# Boolean, true if the region represents BSS
-PROP_BSS = "BSS"
-
-# Number, region memory protection flags, see FLAG_*
-PROP_FLAGS = "Flags"
-
-# String, name of the file
-PROP_FILE_NAME = "FileName"
-
-# String, name of the object file section
-PROP_SECTION_NAME = "SectionName"
-
-# Memory region flags.
-# Read access is allowed
-FLAG_READ = 1
-
-# Write access is allowed
-FLAG_WRITE = 2
-
-# Instruction fetch access is allowed
-FLAG_EXECUTE = 4
-
-class MemoryRegion(object):
- """Memory region object."""
-
- def __init__(self, props):
- self._props = props
-
- def getProperties(self):
- """
- Get region properties. See PROP_* definitions for property names.
- Properties are read only, clients should not try to modify them.
- @return Map of region properties.
- """
- self._props
-
- def getAddress(self):
- """
- Get memory region address.
- @return region address.
- """
- return self._props.get(PROP_ADDRESS)
-
- def getSize(self):
- """
- Get memory region size.
- @return region size.
- """
- return self._props.get(PROP_SIZE)
-
- def getOffset(self):
- """
- Get memory region file offset.
- @return file offset.
- """
- return self._props.get(PROP_OFFSET)
-
- def getFlags(self):
- """
- Get memory region flags.
- @return region flags.
- """
- return self._props.get(PROP_FLAGS, 0)
-
- def getFileName(self):
- """
- Get memory region file name.
- @return file name.
- """
- return self._props.get(PROP_FILE_NAME)
-
- def getSectionName(self):
- """
- Get memory region section name.
- @return section name.
- """
- return self._props.get(PROP_SECTION_NAME)
-
- def __json__(self):
- # This makes it serializable using JSON serializer
- return self._props
-
- def __repr__(self):
- return "MemoryRegion(%s)" % str(self._props)
- __str__ = __repr__
-
-class MemoryMapService(services.Service):
- def getName(self):
- return NAME
-
- def get(self, id, done):
- """
- Retrieve memory map for given context ID.
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def set(self, id, map, done):
- """
- Set memory map for given context ID.
-
- @param id - context ID.
- @param map - memory map data.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add memory map event listener.
- @param listener - memory map event listener to add.
- """
- return NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove memory map event listener.
- @param listener - memory map event listener to remove.
- """
- return NotImplementedError("Abstract method")
-
-class DoneGet(object):
- """
- Client call back interface for get().
- """
- def doneGet(self, token, error, map):
- """
- Called when memory map data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param map - memory map data.
- """
- pass
-
-class DoneSet(object):
- """
- Client call back interface for set().
- """
- def doneSet(self, token, error):
- """
- Called when memory map set command is done.
- @param error - error description if operation failed, None if succeeded.
- """
- pass
-
-class MemoryMapListener(object):
- """
- Service events listener interface.
- """
- def changed(self, context_id):
- """
- Called when context memory map changes.
- @param context_id - context ID.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+MemoryMap service provides information about executable modules (files) mapped (loaded) into target memory.
+"""
+
+from tcf import services
+
+NAME = "MemoryMap"
+
+
+# Memory region property names.
+# Number, region address in memory
+PROP_ADDRESS = "Addr"
+
+# Number, region size
+PROP_SIZE = "Size"
+
+# Number, region offset in the file
+PROP_OFFSET = "Offs"
+
+# Boolean, true if the region represents BSS
+PROP_BSS = "BSS"
+
+# Number, region memory protection flags, see FLAG_*
+PROP_FLAGS = "Flags"
+
+# String, name of the file
+PROP_FILE_NAME = "FileName"
+
+# String, name of the object file section
+PROP_SECTION_NAME = "SectionName"
+
+# Memory region flags.
+# Read access is allowed
+FLAG_READ = 1
+
+# Write access is allowed
+FLAG_WRITE = 2
+
+# Instruction fetch access is allowed
+FLAG_EXECUTE = 4
+
+class MemoryRegion(object):
+ """Memory region object."""
+
+ def __init__(self, props):
+ self._props = props
+
+ def getProperties(self):
+ """
+ Get region properties. See PROP_* definitions for property names.
+ Properties are read only, clients should not try to modify them.
+ @return Map of region properties.
+ """
+ self._props
+
+ def getAddress(self):
+ """
+ Get memory region address.
+ @return region address.
+ """
+ return self._props.get(PROP_ADDRESS)
+
+ def getSize(self):
+ """
+ Get memory region size.
+ @return region size.
+ """
+ return self._props.get(PROP_SIZE)
+
+ def getOffset(self):
+ """
+ Get memory region file offset.
+ @return file offset.
+ """
+ return self._props.get(PROP_OFFSET)
+
+ def getFlags(self):
+ """
+ Get memory region flags.
+ @return region flags.
+ """
+ return self._props.get(PROP_FLAGS, 0)
+
+ def getFileName(self):
+ """
+ Get memory region file name.
+ @return file name.
+ """
+ return self._props.get(PROP_FILE_NAME)
+
+ def getSectionName(self):
+ """
+ Get memory region section name.
+ @return section name.
+ """
+ return self._props.get(PROP_SECTION_NAME)
+
+ def __json__(self):
+ # This makes it serializable using JSON serializer
+ return self._props
+
+ def __repr__(self):
+ return "MemoryRegion(%s)" % str(self._props)
+ __str__ = __repr__
+
+class MemoryMapService(services.Service):
+ def getName(self):
+ return NAME
+
+ def get(self, id, done):
+ """
+ Retrieve memory map for given context ID.
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def set(self, id, map, done):
+ """
+ Set memory map for given context ID.
+
+ @param id - context ID.
+ @param map - memory map data.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add memory map event listener.
+ @param listener - memory map event listener to add.
+ """
+ return NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove memory map event listener.
+ @param listener - memory map event listener to remove.
+ """
+ return NotImplementedError("Abstract method")
+
+class DoneGet(object):
+ """
+ Client call back interface for get().
+ """
+ def doneGet(self, token, error, map):
+ """
+ Called when memory map data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param map - memory map data.
+ """
+ pass
+
+class DoneSet(object):
+ """
+ Client call back interface for set().
+ """
+ def doneSet(self, token, error):
+ """
+ Called when memory map set command is done.
+ @param error - error description if operation failed, None if succeeded.
+ """
+ pass
+
+class MemoryMapListener(object):
+ """
+ Service events listener interface.
+ """
+ def changed(self, context_id):
+ """
+ Called when context memory map changes.
+ @param context_id - context ID.
+ """
+ pass
diff --git a/python/src/tcf/services/pathmap.py b/python/src/tcf/services/pathmap.py
index c232f15ef..588818dbb 100644
--- a/python/src/tcf/services/pathmap.py
+++ b/python/src/tcf/services/pathmap.py
@@ -1,153 +1,153 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-PathMap service manages file path translation across systems.
-"""
-
-from tcf import services
-
-NAME = "PathMap"
-
-# Path mapping rule property names.
-# String, rule ID
-PROP_ID = "ID"
-
-# String, source, or compile-time file path
-PROP_SOURCE = "Source"
-
-# String, destination, or run-time file path
-PROP_DESTINATION = "Destination"
-
-# String
-PROP_HOST = "Host"
-
-# String, file access protocol, see PROTOCOL_*, default is regular file
-PROP_PROTOCOL = "Protocol"
-
-# PROP_PROTOCOL values.
-# Regular file access using system calls
-PROTOCOL_FILE = "file"
-
-# File should be accessed using File System service on host
-PROTOCOL_HOST = "host"
-
-# File should be accessed using File System service on target
-PROTOCOL_TARGET = "target"
-
-class PathMapRule(object):
- """
- PathMapRule represents a single file path mapping rule.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return str(self._props)
-
- def __json__(self):
- return self._props
-
- def getProperties(self):
- """
- Get rule properties. See PROP_* definitions for property names.
- Context properties are read only, clients should not try to modify them.
- @return Map of rule properties.
- """
- return self._props
-
- def getID(self):
- """
- Get rule unique ID.
- Same as getProperties().get(PROP_ID)
- @return rule ID.
- """
- return self._props.get(PROP_ID)
-
- def getSource(self):
- """
- Get compile-time file path.
- Same as getProperties().get(PROP_SOURCE)
- @return compile-time file path.
- """
- return self._props.get(PROP_SOURCE)
-
- def getDestination(self):
- """
- Get run-time file path.
- Same as getProperties().get(PROP_DESTINATION)
- @return run-time file path.
- """
- return self._props.get(PROP_DESTINATION)
-
- def getHost(self):
- """
- Get host name of this rule.
- Same as getProperties().get(PROP_HOST)
- @return host name.
- """
- return self._props.get(PROP_HOST)
-
- def getProtocol(self):
- """
- Get file access protocol name.
- Same as getProperties().get(PROP_PROTOCOL)
- @return protocol name.
- """
- return self._props.get(PROP_PROTOCOL)
-
-
-class PathMapService(services.Service):
- def getName(self):
- return NAME
-
- def get(self, done):
- """
- Retrieve file path mapping rules.
-
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
- def set(self, map, done):
- """
- Set file path mapping rules.
-
- @param map - file path mapping rules.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- return NotImplementedError("Abstract method")
-
-class DoneGet(object):
- """
- Client call back interface for get().
- """
- def doneGet(self, token, error, map):
- """
- Called when file path mapping retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param map - file path mapping data.
- """
- pass
-
-class DoneSet(object):
- """
- Client call back interface for set().
- """
- def doneSet(self, token, error):
- """
- Called when file path mapping transmission is done.
- @param error - error description if operation failed, None if succeeded.
- @param map - memory map data.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+PathMap service manages file path translation across systems.
+"""
+
+from tcf import services
+
+NAME = "PathMap"
+
+# Path mapping rule property names.
+# String, rule ID
+PROP_ID = "ID"
+
+# String, source, or compile-time file path
+PROP_SOURCE = "Source"
+
+# String, destination, or run-time file path
+PROP_DESTINATION = "Destination"
+
+# String
+PROP_HOST = "Host"
+
+# String, file access protocol, see PROTOCOL_*, default is regular file
+PROP_PROTOCOL = "Protocol"
+
+# PROP_PROTOCOL values.
+# Regular file access using system calls
+PROTOCOL_FILE = "file"
+
+# File should be accessed using File System service on host
+PROTOCOL_HOST = "host"
+
+# File should be accessed using File System service on target
+PROTOCOL_TARGET = "target"
+
+class PathMapRule(object):
+ """
+ PathMapRule represents a single file path mapping rule.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return str(self._props)
+
+ def __json__(self):
+ return self._props
+
+ def getProperties(self):
+ """
+ Get rule properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of rule properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Get rule unique ID.
+ Same as getProperties().get(PROP_ID)
+ @return rule ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getSource(self):
+ """
+ Get compile-time file path.
+ Same as getProperties().get(PROP_SOURCE)
+ @return compile-time file path.
+ """
+ return self._props.get(PROP_SOURCE)
+
+ def getDestination(self):
+ """
+ Get run-time file path.
+ Same as getProperties().get(PROP_DESTINATION)
+ @return run-time file path.
+ """
+ return self._props.get(PROP_DESTINATION)
+
+ def getHost(self):
+ """
+ Get host name of this rule.
+ Same as getProperties().get(PROP_HOST)
+ @return host name.
+ """
+ return self._props.get(PROP_HOST)
+
+ def getProtocol(self):
+ """
+ Get file access protocol name.
+ Same as getProperties().get(PROP_PROTOCOL)
+ @return protocol name.
+ """
+ return self._props.get(PROP_PROTOCOL)
+
+
+class PathMapService(services.Service):
+ def getName(self):
+ return NAME
+
+ def get(self, done):
+ """
+ Retrieve file path mapping rules.
+
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+ def set(self, map, done):
+ """
+ Set file path mapping rules.
+
+ @param map - file path mapping rules.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ return NotImplementedError("Abstract method")
+
+class DoneGet(object):
+ """
+ Client call back interface for get().
+ """
+ def doneGet(self, token, error, map):
+ """
+ Called when file path mapping retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param map - file path mapping data.
+ """
+ pass
+
+class DoneSet(object):
+ """
+ Client call back interface for set().
+ """
+ def doneSet(self, token, error):
+ """
+ Called when file path mapping transmission is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param map - memory map data.
+ """
+ pass
diff --git a/python/src/tcf/services/processes.py b/python/src/tcf/services/processes.py
index d5ddef0ca..e7addb3b9 100644
--- a/python/src/tcf/services/processes.py
+++ b/python/src/tcf/services/processes.py
@@ -1,340 +1,340 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-IProcesses service provides access to the target OS's process
-information, allows to start and terminate a process, and allows
-to attach and detach a process for debugging. Debug services,
-like IMemory and IRunControl, require a process to be attached
-before they can access it.
-
-If a process is started by this service, its standard input/output streams are
-available for client to read/write using Streams service. Stream type of such
-streams is set to "Processes".
-"""
-
-from tcf import services
-
-NAME = "Processes"
-
-# Context property names.
-
-# The TCF context ID
-PROP_ID = "ID"
-
-# The TCF parent context ID
-PROP_PARENT_ID = "ParentID"
-
-# Is the context attached
-PROP_ATTACHED = "Attached"
-
-# Can terminate the context
-PROP_CAN_TERMINATE = "CanTerminate"
-
-# Process name. Client UI can show this name to a user
-PROP_NAME = "Name"
-
-# Process standard input stream ID
-PROP_STDIN_ID = "StdInID"
-
-# Process standard output stream ID
-PROP_STDOUT_ID = "StdOutID"
-
-# Process standard error stream ID
-PROP_STDERR_ID = "StdErrID"
-
-
-# Signal property names used by "getSignalList" command.
-
-# Number, bit position in the signal mask
-SIG_INDEX = "Index"
-
-#String, signal name, for example "SIGHUP"
-SIG_NAME = "Name"
-
-# Number, signal code, as defined by OS
-SIG_CODE = "Code"
-
-# String, human readable description of the signal
-SIG_DESCRIPTION = "Description"
-
-
-class ProcessesService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context info for given context ID.
- A context corresponds to an execution thread, process, address space, etc.
- Context IDs are valid across TCF services, so it is allowed to issue
- 'IProcesses.getContext' command with a context that was obtained,
- for example, from Memory service.
- However, 'Processes.getContext' is supposed to return only process specific data,
- If the ID is not a process ID, 'IProcesses.getContext' may not return any
- useful information
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, attached_only, done):
- """
- Retrieve children of given context.
-
- @param parent_context_id - parent context ID. Can be None -
- to retrieve top level of the hierarchy, or one of context IDs retrieved
- by previous getContext or getChildren commands.
- @param attached_only - if True return only attached process IDs.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getSignalList(self, context_id, done):
- """
- Get list of signals that can be send to the process.
- @param context_id - process context ID or None.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def getSignalMask(self, context_id, done):
- """
- Get process or thread signal mask.
- Bits in the mask control how signals should be handled by debug agent.
- When new context is created it inherits the mask from its parent.
- If context is not attached the command will return an error.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def setSignalMask(self, context_id, dont_stop, dont_pass, done):
- """
- Set process or thread signal mask.
- Bits in the mask control how signals should be handled by debug agent.
- If context is not attached the command will return an error.
- @param dont_stop - bit-set of signals that should not suspend execution of the context.
- By default, debugger suspends a context before it receives a signal.
- @param dont_pass - bit-set of signals that should not be delivered to the context.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def signal(self, context_id, signal, done):
- """
- Send a signal to a process or thread.
- @param context_id - context ID.
- @param signal - signal code.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def getEnvironment(self, done):
- """
- Get default set of environment variables used to start a new process.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def start(self, directory, file, command_line, environment, attach, done):
- """
- Start a new process on remote machine.
- @param directory - initial value of working directory for the process.
- @param file - process image file.
- @param command_line - command line arguments for the process.
- Note: the service does NOT add image file name as first argument for the process.
- If a client wants first parameter to be the file name, it should add it itself.
- @param environment - map of environment variables for the process,
- if None then default set of environment variables will be used.
- @param attach - if True debugger should be attached to the process.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add processes service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove processes service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
-
-class ProcessContext(object):
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Processes Context %s]" % self._props
-
- def getProperties(self):
- """
- Get context properties. See PROP_* definitions for property names.
- Context properties are read only, clients should not try to modify them.
- @return Map of context properties.
- """
- return self._props
-
- def getID(self):
- """
- Retrieve context ID.
- Same as getProperties().get('ID')
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Retrieve parent context ID.
- Same as getProperties().get('ParentID')
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getName(self):
- """
- Retrieve human readable context name.
- Same as getProperties().get('Name')
- """
- return self._props.get(PROP_NAME)
-
- def isAttached(self):
- """
- Utility method to read context property PROP_ATTACHED.
- Services like IRunControl, IMemory, IBreakpoints work only with attached processes.
- @return value of PROP_ATTACHED.
- """
- return self._props.get(PROP_ATTACHED)
-
- def canTerminate(self):
- """
- Utility method to read context property PROP_CAN_TERMINATE.
- @return value of PROP_CAN_TERMINATE.
- """
- return self._props.get(PROP_CAN_TERMINATE)
-
- def attach(self, done):
- """
- Attach debugger to a process.
- Services like IRunControl, IMemory, IBreakpoints work only with attached processes.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def detach(self, done):
- """
- Detach debugger from a process.
- Process execution will continue without debugger supervision.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def terminate(self, done):
- """
- Terminate a process.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
-class DoneCommand(object):
- """
- Call-back interface to be called when command is complete.
- """
- def doneCommand(self, token, error):
- pass
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-class DoneGetSignalList(object):
- """
- Call-back interface to be called when "getSignalList" command is complete.
- """
- def doneGetSignalList(self, token, error, list):
- pass
-
-class DoneGetSignalMask(object):
- """
- Call-back interface to be called when "getSignalMask" command is complete.
- """
- def doneGetSignalMask(self, token, error, dont_stop, dont_pass, pending):
- """
- @param token - command handle.
- @param dont_stop - bit-set of signals that should suspend execution of the context.
- @param dont_pass - bit-set of signals that should not be delivered to the context.
- @param pending - bit-set of signals that are generated but not delivered yet.
- Note: "pending" is meaningful only if the context is suspended.
- """
- pass
-
-class DoneGetEnvironment(object):
- """
- Call-back interface to be called when "getEnvironment" command is complete.
- """
- def doneGetEnvironment(self, token, error, environment):
- pass
-
-class DoneStart(object):
- """
- Call-back interface to be called when "start" command is complete.
- """
- def doneStart(self, token, error, process):
- pass
-
-class ProcessesListener(object):
- """
- Process event listener is notified when a process exits.
- Event are reported only for processes that were started by 'start' command.
- """
-
- def exited(self, process_id, exit_code):
- """
- Called when a process exits.
- @param process_id - process context ID
- @param exit_code - if >= 0 - the process exit code,
- if < 0 - process was terminated by a signal, the signal code = -exit_code.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+IProcesses service provides access to the target OS's process
+information, allows to start and terminate a process, and allows
+to attach and detach a process for debugging. Debug services,
+like IMemory and IRunControl, require a process to be attached
+before they can access it.
+
+If a process is started by this service, its standard input/output streams are
+available for client to read/write using Streams service. Stream type of such
+streams is set to "Processes".
+"""
+
+from tcf import services
+
+NAME = "Processes"
+
+# Context property names.
+
+# The TCF context ID
+PROP_ID = "ID"
+
+# The TCF parent context ID
+PROP_PARENT_ID = "ParentID"
+
+# Is the context attached
+PROP_ATTACHED = "Attached"
+
+# Can terminate the context
+PROP_CAN_TERMINATE = "CanTerminate"
+
+# Process name. Client UI can show this name to a user
+PROP_NAME = "Name"
+
+# Process standard input stream ID
+PROP_STDIN_ID = "StdInID"
+
+# Process standard output stream ID
+PROP_STDOUT_ID = "StdOutID"
+
+# Process standard error stream ID
+PROP_STDERR_ID = "StdErrID"
+
+
+# Signal property names used by "getSignalList" command.
+
+# Number, bit position in the signal mask
+SIG_INDEX = "Index"
+
+#String, signal name, for example "SIGHUP"
+SIG_NAME = "Name"
+
+# Number, signal code, as defined by OS
+SIG_CODE = "Code"
+
+# String, human readable description of the signal
+SIG_DESCRIPTION = "Description"
+
+
+class ProcessesService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+ A context corresponds to an execution thread, process, address space, etc.
+ Context IDs are valid across TCF services, so it is allowed to issue
+ 'IProcesses.getContext' command with a context that was obtained,
+ for example, from Memory service.
+ However, 'Processes.getContext' is supposed to return only process specific data,
+ If the ID is not a process ID, 'IProcesses.getContext' may not return any
+ useful information
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, attached_only, done):
+ """
+ Retrieve children of given context.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getContext or getChildren commands.
+ @param attached_only - if True return only attached process IDs.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getSignalList(self, context_id, done):
+ """
+ Get list of signals that can be send to the process.
+ @param context_id - process context ID or None.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getSignalMask(self, context_id, done):
+ """
+ Get process or thread signal mask.
+ Bits in the mask control how signals should be handled by debug agent.
+ When new context is created it inherits the mask from its parent.
+ If context is not attached the command will return an error.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def setSignalMask(self, context_id, dont_stop, dont_pass, done):
+ """
+ Set process or thread signal mask.
+ Bits in the mask control how signals should be handled by debug agent.
+ If context is not attached the command will return an error.
+ @param dont_stop - bit-set of signals that should not suspend execution of the context.
+ By default, debugger suspends a context before it receives a signal.
+ @param dont_pass - bit-set of signals that should not be delivered to the context.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def signal(self, context_id, signal, done):
+ """
+ Send a signal to a process or thread.
+ @param context_id - context ID.
+ @param signal - signal code.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getEnvironment(self, done):
+ """
+ Get default set of environment variables used to start a new process.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def start(self, directory, file, command_line, environment, attach, done):
+ """
+ Start a new process on remote machine.
+ @param directory - initial value of working directory for the process.
+ @param file - process image file.
+ @param command_line - command line arguments for the process.
+ Note: the service does NOT add image file name as first argument for the process.
+ If a client wants first parameter to be the file name, it should add it itself.
+ @param environment - map of environment variables for the process,
+ if None then default set of environment variables will be used.
+ @param attach - if True debugger should be attached to the process.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add processes service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove processes service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class ProcessContext(object):
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Processes Context %s]" % self._props
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Retrieve context ID.
+ Same as getProperties().get('ID')
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Retrieve parent context ID.
+ Same as getProperties().get('ParentID')
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getName(self):
+ """
+ Retrieve human readable context name.
+ Same as getProperties().get('Name')
+ """
+ return self._props.get(PROP_NAME)
+
+ def isAttached(self):
+ """
+ Utility method to read context property PROP_ATTACHED.
+ Services like IRunControl, IMemory, IBreakpoints work only with attached processes.
+ @return value of PROP_ATTACHED.
+ """
+ return self._props.get(PROP_ATTACHED)
+
+ def canTerminate(self):
+ """
+ Utility method to read context property PROP_CAN_TERMINATE.
+ @return value of PROP_CAN_TERMINATE.
+ """
+ return self._props.get(PROP_CAN_TERMINATE)
+
+ def attach(self, done):
+ """
+ Attach debugger to a process.
+ Services like IRunControl, IMemory, IBreakpoints work only with attached processes.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def detach(self, done):
+ """
+ Detach debugger from a process.
+ Process execution will continue without debugger supervision.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def terminate(self, done):
+ """
+ Terminate a process.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+class DoneCommand(object):
+ """
+ Call-back interface to be called when command is complete.
+ """
+ def doneCommand(self, token, error):
+ pass
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class DoneGetSignalList(object):
+ """
+ Call-back interface to be called when "getSignalList" command is complete.
+ """
+ def doneGetSignalList(self, token, error, list):
+ pass
+
+class DoneGetSignalMask(object):
+ """
+ Call-back interface to be called when "getSignalMask" command is complete.
+ """
+ def doneGetSignalMask(self, token, error, dont_stop, dont_pass, pending):
+ """
+ @param token - command handle.
+ @param dont_stop - bit-set of signals that should suspend execution of the context.
+ @param dont_pass - bit-set of signals that should not be delivered to the context.
+ @param pending - bit-set of signals that are generated but not delivered yet.
+ Note: "pending" is meaningful only if the context is suspended.
+ """
+ pass
+
+class DoneGetEnvironment(object):
+ """
+ Call-back interface to be called when "getEnvironment" command is complete.
+ """
+ def doneGetEnvironment(self, token, error, environment):
+ pass
+
+class DoneStart(object):
+ """
+ Call-back interface to be called when "start" command is complete.
+ """
+ def doneStart(self, token, error, process):
+ pass
+
+class ProcessesListener(object):
+ """
+ Process event listener is notified when a process exits.
+ Event are reported only for processes that were started by 'start' command.
+ """
+
+ def exited(self, process_id, exit_code):
+ """
+ Called when a process exits.
+ @param process_id - process context ID
+ @param exit_code - if >= 0 - the process exit code,
+ if < 0 - process was terminated by a signal, the signal code = -exit_code.
+ """
+ pass
diff --git a/python/src/tcf/services/processes_v1.py b/python/src/tcf/services/processes_v1.py
index 75aacd64f..0e31f4cfc 100644
--- a/python/src/tcf/services/processes_v1.py
+++ b/python/src/tcf/services/processes_v1.py
@@ -1,47 +1,47 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Extension of Processes service.
-It provides new "start" command that supports additional parameters.
-"""
-
-from . import processes
-
-NAME = "ProcessesV1"
-
-# Process start parameters
-# Boolean, attach the debugger to the process
-START_ATTACH = "Attach"
-# Boolean, auto-attach process children
-START_ATTACH_CHILDREN = "AttachChildren"
-# Boolean, Use pseudo-terminal for the process standard I/O
-START_USE_TERMINAL = "UseTerminal"
-
-class ProcessesV1Service(processes.ProcessesService):
- def getName(self):
- return NAME
-
- def start(self, directory, file, command_line, environment, params, done):
- """
- Start a new process on remote machine.
- @param directory - initial value of working directory for the process.
- @param file - process image file.
- @param command_line - command line arguments for the process.
- Note: the service does NOT add image file name as first argument for the process.
- If a client wants first parameter to be the file name, it should add it itself.
- @param environment - map of environment variables for the process,
- if None then default set of environment variables will be used.
- @param params - additional process start parameters as map, see START_* for supported keys.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Extension of Processes service.
+It provides new "start" command that supports additional parameters.
+"""
+
+from . import processes
+
+NAME = "ProcessesV1"
+
+# Process start parameters
+# Boolean, attach the debugger to the process
+START_ATTACH = "Attach"
+# Boolean, auto-attach process children
+START_ATTACH_CHILDREN = "AttachChildren"
+# Boolean, Use pseudo-terminal for the process standard I/O
+START_USE_TERMINAL = "UseTerminal"
+
+class ProcessesV1Service(processes.ProcessesService):
+ def getName(self):
+ return NAME
+
+ def start(self, directory, file, command_line, environment, params, done):
+ """
+ Start a new process on remote machine.
+ @param directory - initial value of working directory for the process.
+ @param file - process image file.
+ @param command_line - command line arguments for the process.
+ Note: the service does NOT add image file name as first argument for the process.
+ If a client wants first parameter to be the file name, it should add it itself.
+ @param environment - map of environment variables for the process,
+ if None then default set of environment variables will be used.
+ @param params - additional process start parameters as map, see START_* for supported keys.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
diff --git a/python/src/tcf/services/registers.py b/python/src/tcf/services/registers.py
index 6b8e9556b..dff4f4a69 100644
--- a/python/src/tcf/services/registers.py
+++ b/python/src/tcf/services/registers.py
@@ -1,468 +1,468 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Registers service provides access to target CPU register values and properties.
-"""
-
-from tcf import services
-
-NAME = "Registers"
-
-# Context property names.
-PROP_ID = "ID" # String, ID of the context
-PROP_PARENT_ID = "ParentID" # String, ID of a parent context
-PROP_PROCESS_ID = "ProcessID" # String, process ID
-PROP_NAME = "Name" # String, context name
-PROP_DESCRIPTION = "Description" # String, context description
-PROP_SIZE = "Size" # Number, context size in bytes. Byte arrays in get/set commands should be same size
-PROP_READBLE = "Readable" # Boolean, true if context value can be read
-PROP_READ_ONCE = "ReadOnce" # Boolean, true if reading the context (register) destroys its current value
-PROP_WRITEABLE = "Writeable" # Boolean, true if context value can be written
-PROP_WRITE_ONCE = "WriteOnce" # Boolean, true if register value can not be overwritten - every write counts
-PROP_SIDE_EFFECTS = "SideEffects" # Boolean, true if writing the context can change values of other registers
-PROP_VOLATILE = "Volatile" # Boolean, true if the register value can change even when target is stopped
-PROP_FLOAT = "Float" # Boolean, true if the register value is a floating-point value
-PROP_BIG_ENDIAN = "BigEndian" # Boolean, true if big endian
-PROP_LEFT_TO_RIGHT = "LeftToRight" # Boolean, true if the lowest numbered bit should be shown to user as the left-most bit
-PROP_FIST_BIT = "FirstBit" # Number, bit numbering base (0 or 1) to use when showing bits to user
-PROP_BITS = "Bits" # Number, if context is a bit field, contains the field bit numbers in the parent context
-PROP_VALUES = "Values" # Array of Map, predefined names (mnemonics) for some of context values
-PROP_MEMORY_ADDRESS = "MemoryAddress" # Number, the address of a memory mapped register
-PROP_MEMORY_CONTEXT = "MemoryContext" # String, the context ID of a memory context in which a memory mapped register is located
-PROP_CAN_SEARCH = "CanSearch" # Array of String, a list of attribute names which can be searched for starting on this context
-PROP_ROLE = "Role" # String, the role the register plays in a program execution
-
-# Values of context property "Role".
-ROLE_PC = "PC" # Program counter. Defines instruction to execute next
-ROLE_SP = "SP" # Register defining the current stack pointer location
-ROLE_FP = "FP" # Register defining the current frame pointer location
-ROLE_RET = "RET" # Register used to store the return address for calls
-ROLE_CORE = "CORE" # Indicates register or register groups which belong to the core state
-
-# Search filter properties.
-SEARCH_NAME = "Name" # The name of the property this filter applies too
-SEARCH_EQUAL_VALUE = "EqualValue" # The value which is searched for
-
-
-class RegistersContext(object):
- """
- RegistersContext objects represent register groups, registers and bit fields.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Registers Context %s]" % self._props
-
- def getProperties(self):
- """
- Get context properties. See PROP_* definitions for property names.
- Context properties are read only, clients should not try to modify them.
- @return Map of context properties.
- """
- return self._props
-
- def getID(self):
- """
- Get Context ID.
- @return context ID.
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Get parent context ID.
- @return parent context ID.
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getProcessID(self):
- """
- Get process ID, if applicable.
- @return process ID.
- """
- return self._props.get(PROP_PROCESS_ID)
-
- def getName(self):
- """
- Get context (register, register group, bit field) name.
- @return context name.
- """
- return self._props.get(PROP_NAME)
-
- def getDescription(self):
- """
- Get context description.
- @return context description.
- """
- return self._props.get(PROP_DESCRIPTION)
-
- def getSize(self):
- """
- Get context size in bytes.
- Byte arrays in get()/set() methods should be same size.
- Hardware register can be smaller then this size, for example in case
- when register size is not an even number of bytes. In such case implementation
- should add/remove padding that consist of necessary number of zero bits.
- @return context size in bytes.
- """
- return self._props.get(PROP_SIZE, 0)
-
- def isReadable(self):
- """
- Check if context value can be read.
- @return true if can read value of the context.
- """
- return self._props.get(PROP_READBLE)
-
- def isReadOnce(self):
- """
- Check if reading the context (register) destroys its current value -
- it can be read only once.
- @return true if read-once register.
- """
- return self._props.get(PROP_READ_ONCE)
-
- def isWriteable(self):
- """
- Check if context value can be written.
- @return true if can write value of the context.
- """
- return self._props.get(PROP_WRITEABLE)
-
- def isWriteOnce(self):
- """
- Check if register value can not be overwritten - every write counts.
- @return true if write-once register.
- """
- return self._props.get(PROP_WRITE_ONCE)
-
- def hasSideEffects(self):
- """
- Check if writing the context can change values of other registers.
- @return true if has side effects.
- """
- return self._props.get(PROP_SIDE_EFFECTS)
-
- def isVolatile(self):
- """
- Check if the register value can change even when target is stopped.
- @return true if the register value can change at any time.
- """
- return self._props.get(PROP_VOLATILE)
-
- def isFloat(self):
- """
- Check if the register value is a floating-point value.
- @return true if a floating-point register.
- """
- return self._props.get(PROP_FLOAT)
-
- def isBigEndian(self):
- """
- Check endianness of the context.
- Big endian means decreasing numeric significance with increasing bit number.
- The endianness is used to encode and decode values of get, getm, set and setm commands.
- @return true if big endian.
- """
- return self._props.get(PROP_BIG_ENDIAN)
-
- def isLeftToRight(self):
- """
- Check if the lowest numbered bit (i.e. bit #0 or bit #1 depending on
- getFirstBitNumber() value) should be shown to user as the left-most bit or
- the right-most bit.
- @return true if the first bit is left-most bit.
- """
- return self._props.get(PROP_LEFT_TO_RIGHT)
-
- def getFirstBitNumber(self):
- """
- If the context has bit field children, bit positions of the fields
- can be zero-based or 1-based.
- @return first bit position - 0 or 1.
- """
- return self._props.get(PROP_FIST_BIT, 0)
-
- def getBitNumbers(self):
- """
- If context is a bit field, get the field bit numbers in parent context.
- @return array of bit numbers.
- """
- return self._props.get(PROP_BITS)
-
- def getNamedValues(self):
- """
- A context can have predefined names (mnemonics) for some its values.
- This method returns a list of such named values.
- @return array of named values or None.
- """
- return self._props.get(PROP_VALUES)
-
- def getMemoryAddress(self):
- """
- Get the address of a memory mapped register.
- @return address.
- """
- return self._props.get(PROP_MEMORY_ADDRESS)
-
- def getMemoryContext(self):
- """
- Get the context ID of a memory context in which a memory mapped register is located.
- @return memory context ID.
- """
- return self._props.get(PROP_MEMORY_CONTEXT)
-
- def canSearch(self):
- """
- Get a list of property names which can be searched for starting on this context
- @return collection of property names.
- """
- return self._props.get(PROP_CAN_SEARCH)
-
- def getRole(self):
- """
- Get the role the register plays in a program execution.
- @return role name.
- """
- return self._props.get(PROP_ROLE)
-
- def get(self, done):
- """
- Read value of the context.
- @param done - call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def set(self, value, done):
- """
- Set value of the context.
- @param value - value to write into the context.
- @param done - call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def search(self, filter, done):
- """
- Search register contexts that passes given search filter.
- Search is only supported for properties listed in the "CanSearch" property.
- @param filter - properties bag that defines search filter.
- @param done - call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
-
-class RegistersService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context info for given context ID.
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve contexts available for registers commands.
- A context corresponds to an execution thread, stack frame, registers group, etc.
- A context can belong to a parent context. Contexts hierarchy can be simple
- plain list or it can form a tree. It is up to target agent developers to choose
- layout that is most descriptive for a given target. Context IDs are valid across
- all services. In other words, all services access same hierarchy of contexts,
- with same IDs, however, each service accesses its own subset of context's
- attributes and functionality, which is relevant to that service.
-
- @param parent_context_id - parent context ID. Can be None -
- to retrieve top level of the hierarchy, or one of context IDs retrieved
- by previous getChildren commands.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getm(self, locs, done):
- """
- Read values of multiple locations in registers.
- @param locs - array of data locations.
- @param done - call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def setm(self, locs, value, done):
- """
- Set values of multiple locations in registers.
- @param locs - array of data locations.
- @param value - value to write into the context.
- @param done - call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add registers service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove registers service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
-
-class NamedValue(object):
- """
- A register context can have predefined names (mnemonics) for some its values.
- NamedValue objects represent such values.
- """
- def __init__(self, value, name, description):
- self.value = value
- self.name = name
- self.description = description
-
- def getValue(self):
- """
- Get value associated with the name.
- @return the value as an array of bytes.
- """
- return self.value
-
- def getName(self):
- """
- Get name (mnemonic) of the value.
- @return value name.
- """
- return self.name
-
- def getDescription(self):
- """
- Get human readable description of the value.
- @return value description.
- """
- return self.description
-
-class DoneGet(object):
- """
- 'get' command call back interface.
- """
- def doneGet(self, token, error, value):
- """
- Called when value retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param value - context value as array of bytes.
- """
- pass
-
-class DoneSet(object):
- """
- 'set' command call back interface.
- """
- def doneSet(self, token, error):
- """
- Called when value setting is done.
- @param token - command handle.
- @param error - error description if operation failed, None if succeeded.
- """
- pass
-
-class DoneSearch(object):
- """
- 'search' command call back interface.
- """
- def doneSearch(self, token, error, paths):
- """
- Called when context search is done.
- @param token - command handle.
- @param error - error description if operation failed, None if succeeded.
- @param paths - array of paths to each context with properties matching the filter
- """
- pass
-
-class DoneGetContext(object):
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-
-class RegistersListener(object):
- """
- Registers event listener is notified when registers context hierarchy
- changes, and when a register is modified by the service commands.
- """
-
- def contextChanged(self):
- """
- Called when register context properties changed.
- Most targets have static set of registers and register properties.
- Such targets never generate this event. However, some targets,
- for example, JTAG probes, allow user to modify register definitions.
- Clients should flush all cached register context data.
- """
- pass
-
- def registerChanged(self, id):
- """
- Called when register content was changed and clients
- need to update themselves. Clients, at least, should invalidate
- corresponding cached registers data.
- Not every change is notified - it is not possible,
- only those, which are not caused by normal execution of the debuggee.
- At least, changes caused by "set" command should be notified.
- @param id - register context ID.
- """
- pass
-
-
-class Location(object):
- """
- Class Location represents value location in register context
- """
- def __init__(self, id, offs, size):
- # Register context ID
- self.id = id
- # offset in the context, in bytes
- self.offs = offs
- # value size in bytes
- self.size = size
- def __iter__(self):
- yield self.id
- yield self.offs
- yield self.size
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Registers service provides access to target CPU register values and properties.
+"""
+
+from tcf import services
+
+NAME = "Registers"
+
+# Context property names.
+PROP_ID = "ID" # String, ID of the context
+PROP_PARENT_ID = "ParentID" # String, ID of a parent context
+PROP_PROCESS_ID = "ProcessID" # String, process ID
+PROP_NAME = "Name" # String, context name
+PROP_DESCRIPTION = "Description" # String, context description
+PROP_SIZE = "Size" # Number, context size in bytes. Byte arrays in get/set commands should be same size
+PROP_READBLE = "Readable" # Boolean, true if context value can be read
+PROP_READ_ONCE = "ReadOnce" # Boolean, true if reading the context (register) destroys its current value
+PROP_WRITEABLE = "Writeable" # Boolean, true if context value can be written
+PROP_WRITE_ONCE = "WriteOnce" # Boolean, true if register value can not be overwritten - every write counts
+PROP_SIDE_EFFECTS = "SideEffects" # Boolean, true if writing the context can change values of other registers
+PROP_VOLATILE = "Volatile" # Boolean, true if the register value can change even when target is stopped
+PROP_FLOAT = "Float" # Boolean, true if the register value is a floating-point value
+PROP_BIG_ENDIAN = "BigEndian" # Boolean, true if big endian
+PROP_LEFT_TO_RIGHT = "LeftToRight" # Boolean, true if the lowest numbered bit should be shown to user as the left-most bit
+PROP_FIST_BIT = "FirstBit" # Number, bit numbering base (0 or 1) to use when showing bits to user
+PROP_BITS = "Bits" # Number, if context is a bit field, contains the field bit numbers in the parent context
+PROP_VALUES = "Values" # Array of Map, predefined names (mnemonics) for some of context values
+PROP_MEMORY_ADDRESS = "MemoryAddress" # Number, the address of a memory mapped register
+PROP_MEMORY_CONTEXT = "MemoryContext" # String, the context ID of a memory context in which a memory mapped register is located
+PROP_CAN_SEARCH = "CanSearch" # Array of String, a list of attribute names which can be searched for starting on this context
+PROP_ROLE = "Role" # String, the role the register plays in a program execution
+
+# Values of context property "Role".
+ROLE_PC = "PC" # Program counter. Defines instruction to execute next
+ROLE_SP = "SP" # Register defining the current stack pointer location
+ROLE_FP = "FP" # Register defining the current frame pointer location
+ROLE_RET = "RET" # Register used to store the return address for calls
+ROLE_CORE = "CORE" # Indicates register or register groups which belong to the core state
+
+# Search filter properties.
+SEARCH_NAME = "Name" # The name of the property this filter applies too
+SEARCH_EQUAL_VALUE = "EqualValue" # The value which is searched for
+
+
+class RegistersContext(object):
+ """
+ RegistersContext objects represent register groups, registers and bit fields.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Registers Context %s]" % self._props
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Get Context ID.
+ @return context ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ @return parent context ID.
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getProcessID(self):
+ """
+ Get process ID, if applicable.
+ @return process ID.
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def getName(self):
+ """
+ Get context (register, register group, bit field) name.
+ @return context name.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getDescription(self):
+ """
+ Get context description.
+ @return context description.
+ """
+ return self._props.get(PROP_DESCRIPTION)
+
+ def getSize(self):
+ """
+ Get context size in bytes.
+ Byte arrays in get()/set() methods should be same size.
+ Hardware register can be smaller then this size, for example in case
+ when register size is not an even number of bytes. In such case implementation
+ should add/remove padding that consist of necessary number of zero bits.
+ @return context size in bytes.
+ """
+ return self._props.get(PROP_SIZE, 0)
+
+ def isReadable(self):
+ """
+ Check if context value can be read.
+ @return true if can read value of the context.
+ """
+ return self._props.get(PROP_READBLE)
+
+ def isReadOnce(self):
+ """
+ Check if reading the context (register) destroys its current value -
+ it can be read only once.
+ @return true if read-once register.
+ """
+ return self._props.get(PROP_READ_ONCE)
+
+ def isWriteable(self):
+ """
+ Check if context value can be written.
+ @return true if can write value of the context.
+ """
+ return self._props.get(PROP_WRITEABLE)
+
+ def isWriteOnce(self):
+ """
+ Check if register value can not be overwritten - every write counts.
+ @return true if write-once register.
+ """
+ return self._props.get(PROP_WRITE_ONCE)
+
+ def hasSideEffects(self):
+ """
+ Check if writing the context can change values of other registers.
+ @return true if has side effects.
+ """
+ return self._props.get(PROP_SIDE_EFFECTS)
+
+ def isVolatile(self):
+ """
+ Check if the register value can change even when target is stopped.
+ @return true if the register value can change at any time.
+ """
+ return self._props.get(PROP_VOLATILE)
+
+ def isFloat(self):
+ """
+ Check if the register value is a floating-point value.
+ @return true if a floating-point register.
+ """
+ return self._props.get(PROP_FLOAT)
+
+ def isBigEndian(self):
+ """
+ Check endianness of the context.
+ Big endian means decreasing numeric significance with increasing bit number.
+ The endianness is used to encode and decode values of get, getm, set and setm commands.
+ @return true if big endian.
+ """
+ return self._props.get(PROP_BIG_ENDIAN)
+
+ def isLeftToRight(self):
+ """
+ Check if the lowest numbered bit (i.e. bit #0 or bit #1 depending on
+ getFirstBitNumber() value) should be shown to user as the left-most bit or
+ the right-most bit.
+ @return true if the first bit is left-most bit.
+ """
+ return self._props.get(PROP_LEFT_TO_RIGHT)
+
+ def getFirstBitNumber(self):
+ """
+ If the context has bit field children, bit positions of the fields
+ can be zero-based or 1-based.
+ @return first bit position - 0 or 1.
+ """
+ return self._props.get(PROP_FIST_BIT, 0)
+
+ def getBitNumbers(self):
+ """
+ If context is a bit field, get the field bit numbers in parent context.
+ @return array of bit numbers.
+ """
+ return self._props.get(PROP_BITS)
+
+ def getNamedValues(self):
+ """
+ A context can have predefined names (mnemonics) for some its values.
+ This method returns a list of such named values.
+ @return array of named values or None.
+ """
+ return self._props.get(PROP_VALUES)
+
+ def getMemoryAddress(self):
+ """
+ Get the address of a memory mapped register.
+ @return address.
+ """
+ return self._props.get(PROP_MEMORY_ADDRESS)
+
+ def getMemoryContext(self):
+ """
+ Get the context ID of a memory context in which a memory mapped register is located.
+ @return memory context ID.
+ """
+ return self._props.get(PROP_MEMORY_CONTEXT)
+
+ def canSearch(self):
+ """
+ Get a list of property names which can be searched for starting on this context
+ @return collection of property names.
+ """
+ return self._props.get(PROP_CAN_SEARCH)
+
+ def getRole(self):
+ """
+ Get the role the register plays in a program execution.
+ @return role name.
+ """
+ return self._props.get(PROP_ROLE)
+
+ def get(self, done):
+ """
+ Read value of the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def set(self, value, done):
+ """
+ Set value of the context.
+ @param value - value to write into the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def search(self, filter, done):
+ """
+ Search register contexts that passes given search filter.
+ Search is only supported for properties listed in the "CanSearch" property.
+ @param filter - properties bag that defines search filter.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class RegistersService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve contexts available for registers commands.
+ A context corresponds to an execution thread, stack frame, registers group, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getChildren commands.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getm(self, locs, done):
+ """
+ Read values of multiple locations in registers.
+ @param locs - array of data locations.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def setm(self, locs, value, done):
+ """
+ Set values of multiple locations in registers.
+ @param locs - array of data locations.
+ @param value - value to write into the context.
+ @param done - call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add registers service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove registers service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class NamedValue(object):
+ """
+ A register context can have predefined names (mnemonics) for some its values.
+ NamedValue objects represent such values.
+ """
+ def __init__(self, value, name, description):
+ self.value = value
+ self.name = name
+ self.description = description
+
+ def getValue(self):
+ """
+ Get value associated with the name.
+ @return the value as an array of bytes.
+ """
+ return self.value
+
+ def getName(self):
+ """
+ Get name (mnemonic) of the value.
+ @return value name.
+ """
+ return self.name
+
+ def getDescription(self):
+ """
+ Get human readable description of the value.
+ @return value description.
+ """
+ return self.description
+
+class DoneGet(object):
+ """
+ 'get' command call back interface.
+ """
+ def doneGet(self, token, error, value):
+ """
+ Called when value retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param value - context value as array of bytes.
+ """
+ pass
+
+class DoneSet(object):
+ """
+ 'set' command call back interface.
+ """
+ def doneSet(self, token, error):
+ """
+ Called when value setting is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ """
+ pass
+
+class DoneSearch(object):
+ """
+ 'search' command call back interface.
+ """
+ def doneSearch(self, token, error, paths):
+ """
+ Called when context search is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ @param paths - array of paths to each context with properties matching the filter
+ """
+ pass
+
+class DoneGetContext(object):
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+
+class RegistersListener(object):
+ """
+ Registers event listener is notified when registers context hierarchy
+ changes, and when a register is modified by the service commands.
+ """
+
+ def contextChanged(self):
+ """
+ Called when register context properties changed.
+ Most targets have static set of registers and register properties.
+ Such targets never generate this event. However, some targets,
+ for example, JTAG probes, allow user to modify register definitions.
+ Clients should flush all cached register context data.
+ """
+ pass
+
+ def registerChanged(self, id):
+ """
+ Called when register content was changed and clients
+ need to update themselves. Clients, at least, should invalidate
+ corresponding cached registers data.
+ Not every change is notified - it is not possible,
+ only those, which are not caused by normal execution of the debuggee.
+ At least, changes caused by "set" command should be notified.
+ @param id - register context ID.
+ """
+ pass
+
+
+class Location(object):
+ """
+ Class Location represents value location in register context
+ """
+ def __init__(self, id, offs, size):
+ # Register context ID
+ self.id = id
+ # offset in the context, in bytes
+ self.offs = offs
+ # value size in bytes
+ self.size = size
+ def __iter__(self):
+ yield self.id
+ yield self.offs
+ yield self.size
diff --git a/python/src/tcf/services/remote/BreakpointsProxy.py b/python/src/tcf/services/remote/BreakpointsProxy.py
index 7111c5a48..b7674a3b7 100644
--- a/python/src/tcf/services/remote/BreakpointsProxy.py
+++ b/python/src/tcf/services/remote/BreakpointsProxy.py
@@ -1,149 +1,149 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import breakpoints
-from tcf.channel.Command import Command
-
-class BPCommand(Command):
- def __init__(self, service, cmd, cb, *args):
- super(BPCommand, self).__init__(service.channel, service, cmd, args)
- self.__cb = cb
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- self.__cb.doneCommand(self.token, error)
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "status":
- assert len(args) == 2
- self.listener.breakpointStatusChanged(args[0], args[1])
- elif name == "contextAdded":
- assert len(args) == 1
- self.listener.contextAdded(args[0])
- elif name == "contextChanged":
- assert len(args) == 1
- self.listener.contextChanged(args[0])
- elif name == "contextRemoved":
- assert len(args) == 1
- self.listener.contextRemoved(args[0])
- else:
- raise IOError("Breakpoints service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
-
-class BreakpointsProxy(breakpoints.BreakpointsService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def set(self, properties, done):
- done = self._makeCallback(done)
- return BPCommand(self, "set", done, properties).token
-
- def add(self, properties, done):
- done = self._makeCallback(done)
- return BPCommand(self, "add", done, properties).token
-
- def change(self, properties, done):
- done = self._makeCallback(done)
- return BPCommand(self, "change", done, properties).token
-
- def disable(self, ids, done):
- done = self._makeCallback(done)
- return BPCommand(self, "disable", done, ids).token
-
- def enable(self, ids, done):
- done = self._makeCallback(done)
- return BPCommand(self, "enable", done, ids).token
-
- def remove(self, ids, done):
- done = self._makeCallback(done)
- return BPCommand(self, "remove", done, ids).token
-
- def getIDs(self, done):
- done = self._makeCallback(done)
- service = self
- class GetIDsCommand(Command):
- def __init__(self):
- super(GetIDsCommand, self).__init__(service.channel, service, "getIDs", None)
- def done(self, error, args):
- ids = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- ids = args[1]
- done.doneGetIDs(self.token, error, ids)
- return GetIDsCommand().token
-
- def getProperties(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetPropertiesCommand(Command):
- def __init__(self):
- super(GetPropertiesCommand, self).__init__(service.channel, service, "getProperties", (id,))
- def done(self, error, args):
- map = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- map = args[1]
- done.doneGetProperties(self.token, error, map)
- return GetPropertiesCommand().token
-
- def getStatus(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetStatusCommand(Command):
- def __init__(self):
- super(GetStatusCommand, self).__init__(service.channel, service, "getStatus", (id,))
- def done(self, error, args):
- map = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- map = args[1]
- done.doneGetStatus(self.token, error, map)
- return GetStatusCommand().token
-
- def getCapabilities(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetCapabilitiesCommand(Command):
- def __init__(self):
- super(GetCapabilitiesCommand, self).__init__(service.channel, service, "getCapabilities", (id,))
- def done(self, error, args):
- map = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- map = args[1]
- done.doneGetCapabilities(self.token, error, map)
- return GetCapabilitiesCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import breakpoints
+from tcf.channel.Command import Command
+
+class BPCommand(Command):
+ def __init__(self, service, cmd, cb, *args):
+ super(BPCommand, self).__init__(service.channel, service, cmd, args)
+ self.__cb = cb
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ self.__cb.doneCommand(self.token, error)
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "status":
+ assert len(args) == 2
+ self.listener.breakpointStatusChanged(args[0], args[1])
+ elif name == "contextAdded":
+ assert len(args) == 1
+ self.listener.contextAdded(args[0])
+ elif name == "contextChanged":
+ assert len(args) == 1
+ self.listener.contextChanged(args[0])
+ elif name == "contextRemoved":
+ assert len(args) == 1
+ self.listener.contextRemoved(args[0])
+ else:
+ raise IOError("Breakpoints service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
+
+class BreakpointsProxy(breakpoints.BreakpointsService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def set(self, properties, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "set", done, properties).token
+
+ def add(self, properties, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "add", done, properties).token
+
+ def change(self, properties, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "change", done, properties).token
+
+ def disable(self, ids, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "disable", done, ids).token
+
+ def enable(self, ids, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "enable", done, ids).token
+
+ def remove(self, ids, done):
+ done = self._makeCallback(done)
+ return BPCommand(self, "remove", done, ids).token
+
+ def getIDs(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetIDsCommand(Command):
+ def __init__(self):
+ super(GetIDsCommand, self).__init__(service.channel, service, "getIDs", None)
+ def done(self, error, args):
+ ids = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ ids = args[1]
+ done.doneGetIDs(self.token, error, ids)
+ return GetIDsCommand().token
+
+ def getProperties(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetPropertiesCommand(Command):
+ def __init__(self):
+ super(GetPropertiesCommand, self).__init__(service.channel, service, "getProperties", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetProperties(self.token, error, map)
+ return GetPropertiesCommand().token
+
+ def getStatus(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetStatusCommand(Command):
+ def __init__(self):
+ super(GetStatusCommand, self).__init__(service.channel, service, "getStatus", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetStatus(self.token, error, map)
+ return GetStatusCommand().token
+
+ def getCapabilities(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetCapabilitiesCommand(Command):
+ def __init__(self):
+ super(GetCapabilitiesCommand, self).__init__(service.channel, service, "getCapabilities", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ map = args[1]
+ done.doneGetCapabilities(self.token, error, map)
+ return GetCapabilitiesCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
diff --git a/python/src/tcf/services/remote/DiagnosticsProxy.py b/python/src/tcf/services/remote/DiagnosticsProxy.py
index 24305a1ca..944533ab6 100644
--- a/python/src/tcf/services/remote/DiagnosticsProxy.py
+++ b/python/src/tcf/services/remote/DiagnosticsProxy.py
@@ -1,174 +1,174 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import time
-from tcf import errors
-from tcf.services import diagnostics
-from tcf.channel.Command import Command
-
-class DiagnosticsProxy(diagnostics.DiagnosticsService):
- def __init__(self, channel):
- self.channel = channel
-
- def echo(self, s, done):
- done = self._makeCallback(done)
- service = self
- class EchoCommand(Command):
- def __init__(self):
- super(EchoCommand, self).__init__(service.channel, service, "echo", (s,))
- def done(self, error, args):
- str = None
- if not error:
- assert len(args) == 1
- str = args[0]
- done.doneEcho(self.token, error, str)
- return EchoCommand().token
-
- def echoFP(self, n, done):
- done = self._makeCallback(done)
- service = self
- class EchoFPCommand(Command):
- def __init__(self):
- super(EchoFPCommand, self).__init__(service.channel, service, "echoFP", (n,))
- def done(self, error, args):
- n = None
- if not error:
- assert len(args) == 1
- n = args[0]
- done.doneEchoFP(self.token, error, n)
- return EchoFPCommand().token
-
- def echoERR(self, err, done):
- map = None
- if isinstance(err, errors.ErrorReport):
- map = err.getAttributes()
- else:
- map = {
- errors.ERROR_TIME : int(time.time() * 1000),
- errors.ERROR_CODE : errors.TCF_ERROR_OTHER,
- errors.ERROR_FORMAT : err.message
- }
- done = self._makeCallback(done)
- service = self
- class EchoERRCommand(Command):
- def __init__(self):
- super(EchoERRCommand, self).__init__(service.channel, service, "echoERR", (map,))
- def done(self, error, args):
- err = None
- str = None
- if not error:
- assert len(args) == 2
- err = self.toError(args[0])
- str = args[1]
- done.doneEchoERR(self.token, error, err, str)
- return EchoERRCommand().token
-
- def getTestList(self, done):
- done = self._makeCallback(done)
- service = self
- class GetTestListCommand(Command):
- def __init__(self):
- super(GetTestListCommand, self).__init__(service.channel, service, "getTestList", None)
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = args[1]
- done.doneGetTestList(self.token, error, arr)
- return GetTestListCommand().token
-
- def runTest(self, s, done):
- done = self._makeCallback(done)
- service = self
- class RunTestCommand(Command):
- def __init__(self):
- super(RunTestCommand, self).__init__(service.channel, service, "runTest", (s,))
- def done(self, error, args):
- str = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- str = args[1]
- done.doneRunTest(self.token, error, str)
- return RunTestCommand().token
-
- def cancelTest(self, s, done):
- done = self._makeCallback(done)
- service = self
- class CancelTestCommand(Command):
- def __init__(self):
- super(CancelTestCommand, self).__init__(service.channel, service, "cancelTest", (s,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCancelTest(self.token, error)
- return CancelTestCommand().token
-
- def getSymbol(self, context_id, symbol_name, done):
- done = self._makeCallback(done)
- service = self
- class GetSymbolCommand(Command):
- def __init__(self):
- super(GetSymbolCommand, self).__init__(service.channel, service, "getSymbol", (context_id, symbol_name))
- def done(self, error, args):
- sym = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- sym = _toSymbol(args[1])
- done.doneGetSymbol(self.token, error, sym)
- return GetSymbolCommand().token
-
- def createTestStreams(self, inp_buf_size, out_buf_size, done):
- done = self._makeCallback(done)
- service = self
- class CreateTestStreamsCommand(Command):
- def __init__(self):
- super(CreateTestStreamsCommand, self).__init__(service.channel, service, "createTestStreams", (inp_buf_size, out_buf_size))
- def done(self, error, args):
- inp_id = None
- out_id = None
- if not error:
- assert len(args) == 3
- error = self.toError(args[0])
- inp_id = args[1]
- out_id = args[2]
- done.doneCreateTestStreams(self.token, error, inp_id, out_id)
- return CreateTestStreamsCommand().token
-
- def disposeTestStream(self, id, done):
- done = self._makeCallback(done)
- service = self
- class DisposeTestStreamCommand(Command):
- def __init__(self):
- super(DisposeTestStreamCommand, self).__init__(service.channel, service, "disposeTestStream", (id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneDisposeTestStream(self.token, error)
- return DisposeTestStreamCommand().token
-
- def not_implemented_command(self, done):
- done = self._makeCallback(done)
- service = self
- class NotImplementedCommand(Command):
- def __init__(self):
- super(NotImplementedCommand, self).__init__(service.channel, service, "not implemented command", None)
- def done(self, error, args):
- done.doneNotImplementedCommand(self.token, error)
- return NotImplementedCommand().token
-
-def _toSymbol(o):
- if o is None: return None
- return diagnostics.Symbol(o)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import time
+from tcf import errors
+from tcf.services import diagnostics
+from tcf.channel.Command import Command
+
+class DiagnosticsProxy(diagnostics.DiagnosticsService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def echo(self, s, done):
+ done = self._makeCallback(done)
+ service = self
+ class EchoCommand(Command):
+ def __init__(self):
+ super(EchoCommand, self).__init__(service.channel, service, "echo", (s,))
+ def done(self, error, args):
+ str = None
+ if not error:
+ assert len(args) == 1
+ str = args[0]
+ done.doneEcho(self.token, error, str)
+ return EchoCommand().token
+
+ def echoFP(self, n, done):
+ done = self._makeCallback(done)
+ service = self
+ class EchoFPCommand(Command):
+ def __init__(self):
+ super(EchoFPCommand, self).__init__(service.channel, service, "echoFP", (n,))
+ def done(self, error, args):
+ n = None
+ if not error:
+ assert len(args) == 1
+ n = args[0]
+ done.doneEchoFP(self.token, error, n)
+ return EchoFPCommand().token
+
+ def echoERR(self, err, done):
+ map = None
+ if isinstance(err, errors.ErrorReport):
+ map = err.getAttributes()
+ else:
+ map = {
+ errors.ERROR_TIME : int(time.time() * 1000),
+ errors.ERROR_CODE : errors.TCF_ERROR_OTHER,
+ errors.ERROR_FORMAT : err.message
+ }
+ done = self._makeCallback(done)
+ service = self
+ class EchoERRCommand(Command):
+ def __init__(self):
+ super(EchoERRCommand, self).__init__(service.channel, service, "echoERR", (map,))
+ def done(self, error, args):
+ err = None
+ str = None
+ if not error:
+ assert len(args) == 2
+ err = self.toError(args[0])
+ str = args[1]
+ done.doneEchoERR(self.token, error, err, str)
+ return EchoERRCommand().token
+
+ def getTestList(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetTestListCommand(Command):
+ def __init__(self):
+ super(GetTestListCommand, self).__init__(service.channel, service, "getTestList", None)
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = args[1]
+ done.doneGetTestList(self.token, error, arr)
+ return GetTestListCommand().token
+
+ def runTest(self, s, done):
+ done = self._makeCallback(done)
+ service = self
+ class RunTestCommand(Command):
+ def __init__(self):
+ super(RunTestCommand, self).__init__(service.channel, service, "runTest", (s,))
+ def done(self, error, args):
+ str = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ str = args[1]
+ done.doneRunTest(self.token, error, str)
+ return RunTestCommand().token
+
+ def cancelTest(self, s, done):
+ done = self._makeCallback(done)
+ service = self
+ class CancelTestCommand(Command):
+ def __init__(self):
+ super(CancelTestCommand, self).__init__(service.channel, service, "cancelTest", (s,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCancelTest(self.token, error)
+ return CancelTestCommand().token
+
+ def getSymbol(self, context_id, symbol_name, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetSymbolCommand(Command):
+ def __init__(self):
+ super(GetSymbolCommand, self).__init__(service.channel, service, "getSymbol", (context_id, symbol_name))
+ def done(self, error, args):
+ sym = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ sym = _toSymbol(args[1])
+ done.doneGetSymbol(self.token, error, sym)
+ return GetSymbolCommand().token
+
+ def createTestStreams(self, inp_buf_size, out_buf_size, done):
+ done = self._makeCallback(done)
+ service = self
+ class CreateTestStreamsCommand(Command):
+ def __init__(self):
+ super(CreateTestStreamsCommand, self).__init__(service.channel, service, "createTestStreams", (inp_buf_size, out_buf_size))
+ def done(self, error, args):
+ inp_id = None
+ out_id = None
+ if not error:
+ assert len(args) == 3
+ error = self.toError(args[0])
+ inp_id = args[1]
+ out_id = args[2]
+ done.doneCreateTestStreams(self.token, error, inp_id, out_id)
+ return CreateTestStreamsCommand().token
+
+ def disposeTestStream(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class DisposeTestStreamCommand(Command):
+ def __init__(self):
+ super(DisposeTestStreamCommand, self).__init__(service.channel, service, "disposeTestStream", (id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneDisposeTestStream(self.token, error)
+ return DisposeTestStreamCommand().token
+
+ def not_implemented_command(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class NotImplementedCommand(Command):
+ def __init__(self):
+ super(NotImplementedCommand, self).__init__(service.channel, service, "not implemented command", None)
+ def done(self, error, args):
+ done.doneNotImplementedCommand(self.token, error)
+ return NotImplementedCommand().token
+
+def _toSymbol(o):
+ if o is None: return None
+ return diagnostics.Symbol(o)
diff --git a/python/src/tcf/services/remote/DisassemblyProxy.py b/python/src/tcf/services/remote/DisassemblyProxy.py
index 0ef9bbb04..205f28d03 100644
--- a/python/src/tcf/services/remote/DisassemblyProxy.py
+++ b/python/src/tcf/services/remote/DisassemblyProxy.py
@@ -1,58 +1,58 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import disassembly
-from tcf.channel.Command import Command
-
-class DisassemblyProxy(disassembly.DisassemblyService):
- def __init__(self, channel):
- self.channel = channel
-
- def getCapabilities(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetCapabilitiesCommand(Command):
- def __init__(self):
- super(GetCapabilitiesCommand, self).__init__(service.channel, service, "getCapabilities", (context_id,))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = args[1]
- done.doneGetCapabilities(self.token, error, arr)
- return GetCapabilitiesCommand().token
-
- def disassemble(self, context_id, addr, size, params, done):
- done = self._makeCallback(done)
- service = self
- class DisassembleCommand(Command):
- def __init__(self):
- super(DisassembleCommand, self).__init__(service.channel, service, "disassemble", (context_id, addr, size, params))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = _toDisassemblyArray(args[1])
- done.doneDisassemble(self.token, error, arr)
- return DisassembleCommand().token
-
-
-def _toDisassemblyArray(o):
- if o is None: return None
- return map(_toDisassemblyLine, o)
-
-def _toDisassemblyLine(m):
- addr = m.get("Address")
- size = m.get("Size")
- instruction = m.get("Instruction")
- return disassembly.DisassemblyLine(addr, size, instruction)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import disassembly
+from tcf.channel.Command import Command
+
+class DisassemblyProxy(disassembly.DisassemblyService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getCapabilities(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetCapabilitiesCommand(Command):
+ def __init__(self):
+ super(GetCapabilitiesCommand, self).__init__(service.channel, service, "getCapabilities", (context_id,))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = args[1]
+ done.doneGetCapabilities(self.token, error, arr)
+ return GetCapabilitiesCommand().token
+
+ def disassemble(self, context_id, addr, size, params, done):
+ done = self._makeCallback(done)
+ service = self
+ class DisassembleCommand(Command):
+ def __init__(self):
+ super(DisassembleCommand, self).__init__(service.channel, service, "disassemble", (context_id, addr, size, params))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = _toDisassemblyArray(args[1])
+ done.doneDisassemble(self.token, error, arr)
+ return DisassembleCommand().token
+
+
+def _toDisassemblyArray(o):
+ if o is None: return None
+ return map(_toDisassemblyLine, o)
+
+def _toDisassemblyLine(m):
+ addr = m.get("Address")
+ size = m.get("Size")
+ instruction = m.get("Instruction")
+ return disassembly.DisassemblyLine(addr, size, instruction)
diff --git a/python/src/tcf/services/remote/ExpressionsProxy.py b/python/src/tcf/services/remote/ExpressionsProxy.py
index 462756f3c..f8dfa8179 100644
--- a/python/src/tcf/services/remote/ExpressionsProxy.py
+++ b/python/src/tcf/services/remote/ExpressionsProxy.py
@@ -1,134 +1,134 @@
-# *******************************************************************************
-# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import expressions
-from tcf.channel.Command import Command
-
-class ExpressionsProxy(expressions.ExpressionsService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def assign(self, id, value, done):
- done = self._makeCallback(done)
- service = self
- value = bytearray(value)
- class AssignCommand(Command):
- def __init__(self):
- super(AssignCommand, self).__init__(service.channel, service, "assign", (id, value))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneAssign(self.token, error)
- return AssignCommand().token
-
- def create(self, parent_id, language, expression, done):
- done = self._makeCallback(done)
- service = self
- class CreateCommand(Command):
- def __init__(self):
- super(CreateCommand, self).__init__(service.channel, service, "create", (parent_id, language, expression))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- ctx = expressions.Expression(args[1])
- done.doneCreate(self.token, error, ctx)
- return CreateCommand().token
-
- def dispose(self, id, done):
- done = self._makeCallback(done)
- service = self
- class DisposeCommand(Command):
- def __init__(self):
- super(DisposeCommand, self).__init__(service.channel, service, "dispose", (id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneDispose(self.token, error)
- return DisposeCommand().token
-
- def evaluate(self, id, done):
- done = self._makeCallback(done)
- service = self
- class EvalCommand(Command):
- def __init__(self):
- super(EvalCommand, self).__init__(service.channel, service, "evaluate", (id,))
- def done(self, error, args):
- value = None
- if not error:
- assert len(args) == 3
- value = channel.toByteArray(args[0])
- error = self.toError(args[1])
- props = args[2]
- done.doneEvaluate(self.token, error, expressions.Value(value, props))
- return EvalCommand().token
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def getContext(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = expressions.Expression(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "valueChanged":
- assert len(args) == 1
- self.listener.valueChanged(args[0])
- else:
- raise IOError("Expressions service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
+# *******************************************************************************
+# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import expressions
+from tcf.channel.Command import Command
+
+class ExpressionsProxy(expressions.ExpressionsService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def assign(self, id, value, done):
+ done = self._makeCallback(done)
+ service = self
+ value = bytearray(value)
+ class AssignCommand(Command):
+ def __init__(self):
+ super(AssignCommand, self).__init__(service.channel, service, "assign", (id, value))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneAssign(self.token, error)
+ return AssignCommand().token
+
+ def create(self, parent_id, language, expression, done):
+ done = self._makeCallback(done)
+ service = self
+ class CreateCommand(Command):
+ def __init__(self):
+ super(CreateCommand, self).__init__(service.channel, service, "create", (parent_id, language, expression))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ ctx = expressions.Expression(args[1])
+ done.doneCreate(self.token, error, ctx)
+ return CreateCommand().token
+
+ def dispose(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class DisposeCommand(Command):
+ def __init__(self):
+ super(DisposeCommand, self).__init__(service.channel, service, "dispose", (id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneDispose(self.token, error)
+ return DisposeCommand().token
+
+ def evaluate(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class EvalCommand(Command):
+ def __init__(self):
+ super(EvalCommand, self).__init__(service.channel, service, "evaluate", (id,))
+ def done(self, error, args):
+ value = None
+ if not error:
+ assert len(args) == 3
+ value = channel.toByteArray(args[0])
+ error = self.toError(args[1])
+ props = args[2]
+ done.doneEvaluate(self.token, error, expressions.Value(value, props))
+ return EvalCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = expressions.Expression(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "valueChanged":
+ assert len(args) == 1
+ self.listener.valueChanged(args[0])
+ else:
+ raise IOError("Expressions service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
diff --git a/python/src/tcf/services/remote/FileSystemProxy.py b/python/src/tcf/services/remote/FileSystemProxy.py
index d0a274642..370625f69 100644
--- a/python/src/tcf/services/remote/FileSystemProxy.py
+++ b/python/src/tcf/services/remote/FileSystemProxy.py
@@ -1,509 +1,509 @@
-# *******************************************************************************
-# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import errors, channel
-from tcf.services import filesystem
-from tcf.channel.Command import Command
-
-class Status(filesystem.FileSystemException):
- def __init__(self, status_or_exception, message=None, attrs=None):
- if isinstance(status_or_exception, int):
- super(Status, self).__init__(message)
- self.status = status_or_exception
- self.attrs = attrs
- else:
- super(Status, self).__init__(status_or_exception)
- self.status = errors.TCF_ERROR_OTHER
- self.attrs = {}
-
- def getStatus(self):
- return self.status
-
- def getErrorCode(self):
- return self.attrs.get(errors.ERROR_CODE, 0)
-
- def getAltCode(self):
- return self.attrs.get(errors.ERROR_ALT_CODE, 0)
-
- def getAltOrg(self):
- return self.attrs.get(errors.ERROR_ALT_ORG)
-
- def getAttributes(self):
- return self.attrs
-
-class FileSystemCommand(Command):
- def __init__(self, service, command, args):
- super(FileSystemCommand, self).__init__(service.channel, service, command, args)
-
- def _toSFError(self, data):
- if data is None: return None
- error_code = map.get(errors.ERROR_CODE)
- cmd = self.getCommandString()
- if len(cmd) > 72: cmd = cmd[0, 72] + "..."
- s = Status(error_code,
- "TCF command exception:" +
- "\nCommand: " + cmd +
- "\nException: " + self.toErrorString(data) +
- "\nError code: " + error_code, map)
- caused_by = map.get(errors.ERROR_CAUSED_BY)
- if caused_by is not None: s.initCause(self.toError(caused_by, False))
- return s
-
-class FileSystemProxy(filesystem.FileSystemService):
- def __init__(self, channel):
- self.channel = channel
-
- def close(self, handle, done):
- assert handle.getService() is self
- done = self._makeCallback(done)
- id = handle.id
- service = self
- class CloseCommand(FileSystemCommand):
- def __init__(self):
- super(CloseCommand, self).__init__(service, "close", (id,))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneClose(self.token, s)
- return CloseCommand().token
-
- def setstat(self, path, attrs, done):
- done = self._makeCallback(done)
- dt = _toObject(attrs)
- service = self
- class SetStatCommand(FileSystemCommand):
- def __init__(self):
- super(SetStatCommand, self).__init__(service, "setstat", (path, dt))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneSetStat(self.token, s)
- return SetStatCommand().token
-
- def fsetstat(self, handle, attrs, done):
- done = self._makeCallback(done)
- assert handle.getService() is self
- id = handle.id
- dt = _toObject(attrs)
- service = self
- class FSetStatCommand(FileSystemCommand):
- def __init__(self):
- super(FSetStatCommand, self).__init__(service, "fsetstat", (id, dt))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneSetStat(self.token, s)
- return FSetStatCommand().token
-
- def stat(self, path, done):
- done = self._makeCallback(done)
- service = self
- class StatCommand(FileSystemCommand):
- def __init__(self):
- super(StatCommand, self).__init__(service, "stat", (path,))
- def done(self, error, args):
- s = None
- a = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s: a = _toFileAttrs(args[1])
- done.doneStat(self.token, s, a)
- return StatCommand().token
-
- def fstat(self, handle, done):
- done = self._makeCallback(done)
- assert handle.getService() is self
- id = handle.id
- service = self
- class FStatCommand(FileSystemCommand):
- def __init__(self):
- super(FStatCommand, self).__init__(service, "fstat", (id,))
- def done(self, error, args):
- s = None
- a = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s: a = _toFileAttrs(args[1])
- done.doneStat(self.token, s, a)
- return FStatCommand().token
-
- def lstat(self, path, done):
- done = self._makeCallback(done)
- service = self
- class LStatCommand(FileSystemCommand):
- def __init__(self):
- super(LStatCommand, self).__init__(service, "lstat", (path,))
- def done(self, error, args):
- s = None
- a = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s: a = _toFileAttrs(args[1])
- done.doneStat(self.token, s, a)
- return LStatCommand().token
-
- def mkdir(self, path, attrs, done):
- done = self._makeCallback(done)
- dt = _toObject(attrs)
- service = self
- class MkDirCommand(FileSystemCommand):
- def __init__(self):
- super(MkDirCommand, self).__init__(service, "mkdir", (dt,))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneMkDir(self.token, s)
- return MkDirCommand().token
-
- def open(self, file_name, flags, attrs, done):
- done = self._makeCallback(done)
- dt = _toObject(attrs)
- service = self
- class OpenCommand(FileSystemCommand):
- def __init__(self):
- super(OpenCommand, self).__init__(service, "open", (file_name, flags, dt))
- def done(self, error, args):
- s = None
- h = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s: h = service._toFileHandle(args[1])
- done.doneOpen(self.token, s, h)
- return OpenCommand().token
-
- def opendir(self, path, done):
- done = self._makeCallback(done)
- service = self
- class OpenDirCommand(FileSystemCommand):
- def __init__(self):
- super(OpenDirCommand, self).__init__(service, "opendir", (path,))
- def done(self, error, args):
- s = None
- h = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s: h = service._toFileHandle(args[1])
- done.doneOpen(self.token, s, h)
- return OpenDirCommand().token
-
- def read(self, handle, offset, len, done):
- assert handle.getService() is self
- done = self._makeCallback(done)
- id = handle.id
- service = self
- class ReadCommand(FileSystemCommand):
- def __init__(self):
- super(ReadCommand, self).__init__(service, "read", (id, offset, len))
- def done(self, error, args):
- s = None
- b = None
- eof = False
- if error:
- s = Status(error)
- else:
- assert len(args) == 3
- s = self._toSFError(args[1])
- if not s:
- b = channel.toByteArray(args[0])
- eof = args[2]
- done.doneRead(self.token, s, b, eof)
- return ReadCommand().token
-
- def readdir(self, handle, done):
- assert handle.getService() is self
- done = self._makeCallback(done)
- id = handle.id
- service = self
- class ReadDirCommand(FileSystemCommand):
- def __init__(self):
- super(ReadDirCommand, self).__init__(service, "readdir", (id,))
- def done(self, error, args):
- s = None
- b = None
- eof = False
- if error:
- s = Status(error)
- else:
- assert len(args) == 3
- s = self._toSFError(args[1])
- if not s:
- b = _toDirEntryArray(args[0])
- eof = args[2]
- done.doneReadDir(self.token, s, b, eof)
- return ReadDirCommand().token
-
- def roots(self, done):
- done = self._makeCallback(done)
- service = self
- class RootCommand(FileSystemCommand):
- def __init__(self):
- super(RootCommand, self).__init__(service, "roots", None)
- def done(self, error, args):
- s = None
- b = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[1])
- if not s:
- b = _toDirEntryArray(args[0])
- done.doneRoots(self.token, s, b)
- return RootCommand().token
-
- def readlink(self, path, done):
- done = self._makeCallback(done)
- service = self
- class ReadLinkCommand(FileSystemCommand):
- def __init__(self):
- super(ReadLinkCommand, self).__init__(service, "readlink", (path,))
- def done(self, error, args):
- s = None
- p = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s:
- p = args[1]
- done.doneReadLink(self.token, s, p)
- return ReadLinkCommand().token
-
- def realpath(self, path, done):
- done = self._makeCallback(done)
- service = self
- class RealPathCommand(FileSystemCommand):
- def __init__(self):
- super(RealPathCommand, self).__init__(service, "realpath", (path,))
- def done(self, error, args):
- s = None
- p = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 2
- s = self._toSFError(args[0])
- if not s:
- p = args[1]
- done.doneRealPath(self.token, s, p)
- return RealPathCommand().token
-
- def remove(self, file_name, done):
- done = self._makeCallback(done)
- service = self
- class RemoveCommand(FileSystemCommand):
- def __init__(self):
- super(RemoveCommand, self).__init__(service, "remove", (file_name,))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneRemove(self.token, s)
- return RemoveCommand().token
-
- def rename(self, old_path, new_path, done):
- done = self._makeCallback(done)
- service = self
- class RenameCommand(FileSystemCommand):
- def __init__(self):
- super(RenameCommand, self).__init__(service, "rename", (old_path, new_path))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneRename(self.token, s)
- return RenameCommand().token
-
- def rmdir(self, path, done):
- done = self._makeCallback(done)
- service = self
- class RmDirCommand(FileSystemCommand):
- def __init__(self):
- super(RmDirCommand, self).__init__(service, "rmdir", (path,))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneRemove(self.token, s)
- return RmDirCommand().token
-
- def symlink(self, link_path, target_path, done):
- done = self._makeCallback(done)
- service = self
- class SymLinkCommand(FileSystemCommand):
- def __init__(self):
- super(SymLinkCommand, self).__init__(service, "symlink", (link_path, target_path))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneSymLink(self.token, s)
- return SymLinkCommand().token
-
- def write(self, handle, offset, data, data_pos, data_size, done):
- assert handle.getService() is self
- done = self._makeCallback(done)
- id = handle.id
- binary = bytearray(data[data_pos:data_pos+data_size])
- service = self
- class WriteCommand(FileSystemCommand):
- def __init__(self):
- super(WriteCommand, self).__init__(service, "write", (id, offset, binary))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneWrite(self.token, s)
- return WriteCommand().token
-
- def copy(self, src_path, dst_path, copy_permissions, copy_uidgid, done):
- done = self._makeCallback(done)
- service = self
- class CopyCommand(FileSystemCommand):
- def __init__(self):
- super(CopyCommand, self).__init__(service, "copy",
- (id, src_path, dst_path, copy_permissions, copy_uidgid))
- def done(self, error, args):
- s = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 1
- s = self._toSFError(args[0])
- done.doneCopy(self.token, s)
- return CopyCommand().token
-
- def user(self, done):
- done = self._makeCallback(done)
- service = self
- class UserCommand(FileSystemCommand):
- def __init__(self):
- super(UserCommand, self).__init__(service, "user", None)
- def done(self, error, args):
- s = None
- r_uid = 0
- e_uid = 0
- r_gid = 0
- e_gid = 0
- home = None
- if error:
- s = Status(error)
- else:
- assert len(args) == 5
- r_uid, e_uid, r_gid, e_gid, home = args
- done.doneUser(self.token, s, r_uid, e_uid, r_gid, e_gid, home)
- return UserCommand().token
-
- def _toFileHandle(self, o):
- if o is None: return None
- return filesystem.FileHandle(self, o)
-
-def _toObject(attrs):
- if attrs is None: return None
- m = {}
- if attrs.attributes is not None: m.update(attrs.attributes)
- if (attrs.flags & filesystem.ATTR_SIZE) != 0:
- m["Size"] = attrs.size
- if (attrs.flags & filesystem.ATTR_UIDGID) != 0:
- m["UID"] = attrs.uid
- m["GID"] = attrs.gid
- if (attrs.flags & filesystem.ATTR_PERMISSIONS) != 0:
- m["Permissions"] = attrs.permissions
- if (attrs.flags & filesystem.ATTR_ACMODTIME) != 0:
- m["ATime"] = attrs.atime
- m["MTime"] = attrs.mtime
- return m
-
-def _toFileAttrs(m):
- if m is None: return None
- flags = 0
- size = 0
- uid = 0
- gid = 0
- permissions = 0
- atime = 0
- mtime = 0
- n = m.pop("Size", None)
- if n is not None:
- size = n
- flags |= filesystem.ATTR_SIZE
- n1 = m.pop("UID", None)
- n2 = m.pop("GID", None)
- if n1 is not None and n2 is not None:
- uid = n1
- gid = n2
- flags |= filesystem.ATTR_UIDGID
- n = m.pop("Permissions", None)
- if n is not None:
- permissions = n
- flags |= filesystem.ATTR_PERMISSIONS
- n1 = m.pop("ATime", None)
- n2 = m.pop("MTime", None)
- if n1 is not None and n2 is not None:
- atime = n1
- mtime = n2
- flags |= filesystem.ATTR_ACMODTIME
- return filesystem.FileAttrs(flags, size, uid, gid, permissions, atime, mtime, m)
-
-def _toDirEntryArray(o):
- if o is None: return None
- res = []
- for m in o:
- entry = filesystem.DirEntry(m.get("FileName"), m.get("LongName"), _toFileAttrs(m.get("Attrs")))
- res.append(entry)
- return res
+# *******************************************************************************
+# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import errors, channel
+from tcf.services import filesystem
+from tcf.channel.Command import Command
+
+class Status(filesystem.FileSystemException):
+ def __init__(self, status_or_exception, message=None, attrs=None):
+ if isinstance(status_or_exception, int):
+ super(Status, self).__init__(message)
+ self.status = status_or_exception
+ self.attrs = attrs
+ else:
+ super(Status, self).__init__(status_or_exception)
+ self.status = errors.TCF_ERROR_OTHER
+ self.attrs = {}
+
+ def getStatus(self):
+ return self.status
+
+ def getErrorCode(self):
+ return self.attrs.get(errors.ERROR_CODE, 0)
+
+ def getAltCode(self):
+ return self.attrs.get(errors.ERROR_ALT_CODE, 0)
+
+ def getAltOrg(self):
+ return self.attrs.get(errors.ERROR_ALT_ORG)
+
+ def getAttributes(self):
+ return self.attrs
+
+class FileSystemCommand(Command):
+ def __init__(self, service, command, args):
+ super(FileSystemCommand, self).__init__(service.channel, service, command, args)
+
+ def _toSFError(self, data):
+ if data is None: return None
+ error_code = map.get(errors.ERROR_CODE)
+ cmd = self.getCommandString()
+ if len(cmd) > 72: cmd = cmd[0, 72] + "..."
+ s = Status(error_code,
+ "TCF command exception:" +
+ "\nCommand: " + cmd +
+ "\nException: " + self.toErrorString(data) +
+ "\nError code: " + error_code, map)
+ caused_by = map.get(errors.ERROR_CAUSED_BY)
+ if caused_by is not None: s.initCause(self.toError(caused_by, False))
+ return s
+
+class FileSystemProxy(filesystem.FileSystemService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def close(self, handle, done):
+ assert handle.getService() is self
+ done = self._makeCallback(done)
+ id = handle.id
+ service = self
+ class CloseCommand(FileSystemCommand):
+ def __init__(self):
+ super(CloseCommand, self).__init__(service, "close", (id,))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneClose(self.token, s)
+ return CloseCommand().token
+
+ def setstat(self, path, attrs, done):
+ done = self._makeCallback(done)
+ dt = _toObject(attrs)
+ service = self
+ class SetStatCommand(FileSystemCommand):
+ def __init__(self):
+ super(SetStatCommand, self).__init__(service, "setstat", (path, dt))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneSetStat(self.token, s)
+ return SetStatCommand().token
+
+ def fsetstat(self, handle, attrs, done):
+ done = self._makeCallback(done)
+ assert handle.getService() is self
+ id = handle.id
+ dt = _toObject(attrs)
+ service = self
+ class FSetStatCommand(FileSystemCommand):
+ def __init__(self):
+ super(FSetStatCommand, self).__init__(service, "fsetstat", (id, dt))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneSetStat(self.token, s)
+ return FSetStatCommand().token
+
+ def stat(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class StatCommand(FileSystemCommand):
+ def __init__(self):
+ super(StatCommand, self).__init__(service, "stat", (path,))
+ def done(self, error, args):
+ s = None
+ a = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s: a = _toFileAttrs(args[1])
+ done.doneStat(self.token, s, a)
+ return StatCommand().token
+
+ def fstat(self, handle, done):
+ done = self._makeCallback(done)
+ assert handle.getService() is self
+ id = handle.id
+ service = self
+ class FStatCommand(FileSystemCommand):
+ def __init__(self):
+ super(FStatCommand, self).__init__(service, "fstat", (id,))
+ def done(self, error, args):
+ s = None
+ a = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s: a = _toFileAttrs(args[1])
+ done.doneStat(self.token, s, a)
+ return FStatCommand().token
+
+ def lstat(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class LStatCommand(FileSystemCommand):
+ def __init__(self):
+ super(LStatCommand, self).__init__(service, "lstat", (path,))
+ def done(self, error, args):
+ s = None
+ a = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s: a = _toFileAttrs(args[1])
+ done.doneStat(self.token, s, a)
+ return LStatCommand().token
+
+ def mkdir(self, path, attrs, done):
+ done = self._makeCallback(done)
+ dt = _toObject(attrs)
+ service = self
+ class MkDirCommand(FileSystemCommand):
+ def __init__(self):
+ super(MkDirCommand, self).__init__(service, "mkdir", (dt,))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneMkDir(self.token, s)
+ return MkDirCommand().token
+
+ def open(self, file_name, flags, attrs, done):
+ done = self._makeCallback(done)
+ dt = _toObject(attrs)
+ service = self
+ class OpenCommand(FileSystemCommand):
+ def __init__(self):
+ super(OpenCommand, self).__init__(service, "open", (file_name, flags, dt))
+ def done(self, error, args):
+ s = None
+ h = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s: h = service._toFileHandle(args[1])
+ done.doneOpen(self.token, s, h)
+ return OpenCommand().token
+
+ def opendir(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class OpenDirCommand(FileSystemCommand):
+ def __init__(self):
+ super(OpenDirCommand, self).__init__(service, "opendir", (path,))
+ def done(self, error, args):
+ s = None
+ h = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s: h = service._toFileHandle(args[1])
+ done.doneOpen(self.token, s, h)
+ return OpenDirCommand().token
+
+ def read(self, handle, offset, len, done):
+ assert handle.getService() is self
+ done = self._makeCallback(done)
+ id = handle.id
+ service = self
+ class ReadCommand(FileSystemCommand):
+ def __init__(self):
+ super(ReadCommand, self).__init__(service, "read", (id, offset, len))
+ def done(self, error, args):
+ s = None
+ b = None
+ eof = False
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 3
+ s = self._toSFError(args[1])
+ if not s:
+ b = channel.toByteArray(args[0])
+ eof = args[2]
+ done.doneRead(self.token, s, b, eof)
+ return ReadCommand().token
+
+ def readdir(self, handle, done):
+ assert handle.getService() is self
+ done = self._makeCallback(done)
+ id = handle.id
+ service = self
+ class ReadDirCommand(FileSystemCommand):
+ def __init__(self):
+ super(ReadDirCommand, self).__init__(service, "readdir", (id,))
+ def done(self, error, args):
+ s = None
+ b = None
+ eof = False
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 3
+ s = self._toSFError(args[1])
+ if not s:
+ b = _toDirEntryArray(args[0])
+ eof = args[2]
+ done.doneReadDir(self.token, s, b, eof)
+ return ReadDirCommand().token
+
+ def roots(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class RootCommand(FileSystemCommand):
+ def __init__(self):
+ super(RootCommand, self).__init__(service, "roots", None)
+ def done(self, error, args):
+ s = None
+ b = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[1])
+ if not s:
+ b = _toDirEntryArray(args[0])
+ done.doneRoots(self.token, s, b)
+ return RootCommand().token
+
+ def readlink(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class ReadLinkCommand(FileSystemCommand):
+ def __init__(self):
+ super(ReadLinkCommand, self).__init__(service, "readlink", (path,))
+ def done(self, error, args):
+ s = None
+ p = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s:
+ p = args[1]
+ done.doneReadLink(self.token, s, p)
+ return ReadLinkCommand().token
+
+ def realpath(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class RealPathCommand(FileSystemCommand):
+ def __init__(self):
+ super(RealPathCommand, self).__init__(service, "realpath", (path,))
+ def done(self, error, args):
+ s = None
+ p = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 2
+ s = self._toSFError(args[0])
+ if not s:
+ p = args[1]
+ done.doneRealPath(self.token, s, p)
+ return RealPathCommand().token
+
+ def remove(self, file_name, done):
+ done = self._makeCallback(done)
+ service = self
+ class RemoveCommand(FileSystemCommand):
+ def __init__(self):
+ super(RemoveCommand, self).__init__(service, "remove", (file_name,))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneRemove(self.token, s)
+ return RemoveCommand().token
+
+ def rename(self, old_path, new_path, done):
+ done = self._makeCallback(done)
+ service = self
+ class RenameCommand(FileSystemCommand):
+ def __init__(self):
+ super(RenameCommand, self).__init__(service, "rename", (old_path, new_path))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneRename(self.token, s)
+ return RenameCommand().token
+
+ def rmdir(self, path, done):
+ done = self._makeCallback(done)
+ service = self
+ class RmDirCommand(FileSystemCommand):
+ def __init__(self):
+ super(RmDirCommand, self).__init__(service, "rmdir", (path,))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneRemove(self.token, s)
+ return RmDirCommand().token
+
+ def symlink(self, link_path, target_path, done):
+ done = self._makeCallback(done)
+ service = self
+ class SymLinkCommand(FileSystemCommand):
+ def __init__(self):
+ super(SymLinkCommand, self).__init__(service, "symlink", (link_path, target_path))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneSymLink(self.token, s)
+ return SymLinkCommand().token
+
+ def write(self, handle, offset, data, data_pos, data_size, done):
+ assert handle.getService() is self
+ done = self._makeCallback(done)
+ id = handle.id
+ binary = bytearray(data[data_pos:data_pos+data_size])
+ service = self
+ class WriteCommand(FileSystemCommand):
+ def __init__(self):
+ super(WriteCommand, self).__init__(service, "write", (id, offset, binary))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneWrite(self.token, s)
+ return WriteCommand().token
+
+ def copy(self, src_path, dst_path, copy_permissions, copy_uidgid, done):
+ done = self._makeCallback(done)
+ service = self
+ class CopyCommand(FileSystemCommand):
+ def __init__(self):
+ super(CopyCommand, self).__init__(service, "copy",
+ (id, src_path, dst_path, copy_permissions, copy_uidgid))
+ def done(self, error, args):
+ s = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 1
+ s = self._toSFError(args[0])
+ done.doneCopy(self.token, s)
+ return CopyCommand().token
+
+ def user(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class UserCommand(FileSystemCommand):
+ def __init__(self):
+ super(UserCommand, self).__init__(service, "user", None)
+ def done(self, error, args):
+ s = None
+ r_uid = 0
+ e_uid = 0
+ r_gid = 0
+ e_gid = 0
+ home = None
+ if error:
+ s = Status(error)
+ else:
+ assert len(args) == 5
+ r_uid, e_uid, r_gid, e_gid, home = args
+ done.doneUser(self.token, s, r_uid, e_uid, r_gid, e_gid, home)
+ return UserCommand().token
+
+ def _toFileHandle(self, o):
+ if o is None: return None
+ return filesystem.FileHandle(self, o)
+
+def _toObject(attrs):
+ if attrs is None: return None
+ m = {}
+ if attrs.attributes is not None: m.update(attrs.attributes)
+ if (attrs.flags & filesystem.ATTR_SIZE) != 0:
+ m["Size"] = attrs.size
+ if (attrs.flags & filesystem.ATTR_UIDGID) != 0:
+ m["UID"] = attrs.uid
+ m["GID"] = attrs.gid
+ if (attrs.flags & filesystem.ATTR_PERMISSIONS) != 0:
+ m["Permissions"] = attrs.permissions
+ if (attrs.flags & filesystem.ATTR_ACMODTIME) != 0:
+ m["ATime"] = attrs.atime
+ m["MTime"] = attrs.mtime
+ return m
+
+def _toFileAttrs(m):
+ if m is None: return None
+ flags = 0
+ size = 0
+ uid = 0
+ gid = 0
+ permissions = 0
+ atime = 0
+ mtime = 0
+ n = m.pop("Size", None)
+ if n is not None:
+ size = n
+ flags |= filesystem.ATTR_SIZE
+ n1 = m.pop("UID", None)
+ n2 = m.pop("GID", None)
+ if n1 is not None and n2 is not None:
+ uid = n1
+ gid = n2
+ flags |= filesystem.ATTR_UIDGID
+ n = m.pop("Permissions", None)
+ if n is not None:
+ permissions = n
+ flags |= filesystem.ATTR_PERMISSIONS
+ n1 = m.pop("ATime", None)
+ n2 = m.pop("MTime", None)
+ if n1 is not None and n2 is not None:
+ atime = n1
+ mtime = n2
+ flags |= filesystem.ATTR_ACMODTIME
+ return filesystem.FileAttrs(flags, size, uid, gid, permissions, atime, mtime, m)
+
+def _toDirEntryArray(o):
+ if o is None: return None
+ res = []
+ for m in o:
+ entry = filesystem.DirEntry(m.get("FileName"), m.get("LongName"), _toFileAttrs(m.get("Attrs")))
+ res.append(entry)
+ return res
diff --git a/python/src/tcf/services/remote/LineNumbersProxy.py b/python/src/tcf/services/remote/LineNumbersProxy.py
index ad567d225..7452cc761 100644
--- a/python/src/tcf/services/remote/LineNumbersProxy.py
+++ b/python/src/tcf/services/remote/LineNumbersProxy.py
@@ -1,67 +1,67 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import linenumbers
-from tcf.channel.Command import Command
-
-class LineNumbersProxy(linenumbers.LineNumbersService):
-
- def __init__(self, channel):
- self.channel = channel
-
- def mapToSource(self, context_id, start_address, end_address, done):
- done = self._makeCallback(done)
- service = self
- class MapCommand(Command):
- def __init__(self):
- super(MapCommand, self).__init__(service.channel, service,
- "mapToSource", (context_id, start_address, end_address))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = _toCodeAreaArray(args[1])
- done.doneMapToSource(self.token, error, arr)
- return MapCommand().token
-
- def mapToMemory(self, context_id, file, line, column, done):
- done = self._makeCallback(done)
- service = self
- class MapCommand(Command):
- def __init__(self):
- super(MapCommand, self).__init__(service.channel, service,
- "mapToMemory", (context_id, file, line, column))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = _toCodeAreaArray(args[1])
- done.doneMapToMemory(self.token, error, arr)
- return MapCommand().token
-
-def _toCodeAreaArray(o):
- if not o: return None
- arr = []
- directory = None
- file = None
- for area in o:
- directory = area.get("Dir", directory)
- file = area.get("File", file)
- arr.append(linenumbers.CodeArea(directory, file,
- area.get("SLine", 0), area.get("SCol", 0),
- area.get("ELine", 0), area.get("ECol", 0),
- area.get("SAddr"), area.get("EAddr"),
- area.get("ISA", 0),
- area.get("IsStmt"), area.get("BasicBlock"),
- area.get("PrologueEnd"), area.get("EpilogueBegin")))
- return arr
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import linenumbers
+from tcf.channel.Command import Command
+
+class LineNumbersProxy(linenumbers.LineNumbersService):
+
+ def __init__(self, channel):
+ self.channel = channel
+
+ def mapToSource(self, context_id, start_address, end_address, done):
+ done = self._makeCallback(done)
+ service = self
+ class MapCommand(Command):
+ def __init__(self):
+ super(MapCommand, self).__init__(service.channel, service,
+ "mapToSource", (context_id, start_address, end_address))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = _toCodeAreaArray(args[1])
+ done.doneMapToSource(self.token, error, arr)
+ return MapCommand().token
+
+ def mapToMemory(self, context_id, file, line, column, done):
+ done = self._makeCallback(done)
+ service = self
+ class MapCommand(Command):
+ def __init__(self):
+ super(MapCommand, self).__init__(service.channel, service,
+ "mapToMemory", (context_id, file, line, column))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = _toCodeAreaArray(args[1])
+ done.doneMapToMemory(self.token, error, arr)
+ return MapCommand().token
+
+def _toCodeAreaArray(o):
+ if not o: return None
+ arr = []
+ directory = None
+ file = None
+ for area in o:
+ directory = area.get("Dir", directory)
+ file = area.get("File", file)
+ arr.append(linenumbers.CodeArea(directory, file,
+ area.get("SLine", 0), area.get("SCol", 0),
+ area.get("ELine", 0), area.get("ECol", 0),
+ area.get("SAddr"), area.get("EAddr"),
+ area.get("ISA", 0),
+ area.get("IsStmt"), area.get("BasicBlock"),
+ area.get("PrologueEnd"), area.get("EpilogueBegin")))
+ return arr
diff --git a/python/src/tcf/services/remote/LocatorProxy.py b/python/src/tcf/services/remote/LocatorProxy.py
index 8072118c1..d9963686e 100644
--- a/python/src/tcf/services/remote/LocatorProxy.py
+++ b/python/src/tcf/services/remote/LocatorProxy.py
@@ -1,149 +1,149 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import protocol, peer, channel
-from tcf.services import locator
-from tcf.channel.Command import Command
-
-class Peer(peer.TransientPeer):
- def __init__(self, parent, attrs):
- super(Peer, self).__init__(attrs)
- self.parent = parent
- def openChannel(self):
- assert protocol.isDispatchThread()
- c = self.parent.openChannel()
- c.redirect(self.getID())
- return c
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, proxy):
- self.proxy = proxy
- self.channel = proxy.channel
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "peerAdded":
- assert len(args) == 1
- _peer = Peer(self.channel.getRemotePeer(), args[0])
- if self.proxy.peers.get(_peer.getID()):
- protocol.log("Invalid peerAdded event", Exception())
- return
- self.proxy.peers[_peer.getID()] = _peer
- for l in self.proxy.listeners:
- try:
- l.peerAdded(_peer)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- elif name == "peerChanged":
- assert len(args) == 1
- m = args[0]
- if not m: raise Exception("Locator service: invalid peerChanged event - no peer ID")
- _peer = self.proxy.peers.get(m.get(peer.ATTR_ID))
- if not _peer: return
- self.proxy.peers[_peer.getID()] = _peer
- for l in self.proxy.listeners:
- try:
- l.peerChanged(_peer)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- elif name == "peerRemoved":
- assert len(args) == 1
- id = args[0]
- _peer = self.proxy.peers.get(id)
- if not _peer: return
- del self.proxy.peers[id]
- for l in self.proxy.listeners:
- try:
- l.peerRemoved(id)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- elif name == "peerHeartBeat":
- assert len(args) == 1
- id = args[0]
- _peer = self.proxy.peers.get(id)
- if not _peer: return
- for l in self.proxy.listeners:
- try:
- l.peerHeartBeat(id)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- else:
- raise IOError("Locator service: unknown event: " + name)
- except Exception as x:
- self.channel.terminate(x)
-
-class LocatorProxy(locator.LocatorService):
- def __init__(self, channel):
- self.channel = channel;
- self.peers = {}
- self.listeners = []
- self.get_peers_done = False
- self.event_listener = ChannelEventListener(self)
- channel.addEventListener(self, self.event_listener)
-
- def getPeers(self):
- return self.peers
-
- def redirect(self, _peer, done):
- done = self._makeCallback(done)
- service = self
- class RedirectCommand(Command):
- def __init__(self):
- super(RedirectCommand, self).__init__(service.channel, service, "redirect", [_peer])
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneRedirect(self.token, error)
- return RedirectCommand().token
-
- def sync(self, done):
- done = self._makeCallback(done)
- service = self
- class SyncCommand(Command):
- def __init__(self):
- super(SyncCommand, self).__init__(service.channel, service, "sync", None)
- def done(self, error, args):
- if error: service.channel.terminate(error)
- done.doneSync(self.token)
- return SyncCommand().token
-
- def addListener(self, listener):
- self.listeners.append(listener)
- if not self.get_peers_done:
- service = self
- class GetPeersCommand(Command):
- def __init__(self):
- super(GetPeersCommand, self).__init__(service.channel, service, "getPeers", None)
- def done(self, error, args):
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if error:
- protocol.log("Locator error", error)
- return
- c = args[1]
- if c:
- for m in c:
- id = m.get(peer.ATTR_ID)
- if service.peers.get(id): continue;
- _peer = Peer(service.channel.getRemotePeer(), m)
- service.peers[id] = _peer
- for l in service.listeners:
- try:
- l.peerAdded(_peer)
- except Exception as x:
- protocol.log("Unhandled exception in Locator listener", x)
- GetPeersCommand()
- self.get_peers_done = True
-
- def removeListener(self, listener):
- self.listeners.remove(listener)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import protocol, peer, channel
+from tcf.services import locator
+from tcf.channel.Command import Command
+
+class Peer(peer.TransientPeer):
+ def __init__(self, parent, attrs):
+ super(Peer, self).__init__(attrs)
+ self.parent = parent
+ def openChannel(self):
+ assert protocol.isDispatchThread()
+ c = self.parent.openChannel()
+ c.redirect(self.getID())
+ return c
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, proxy):
+ self.proxy = proxy
+ self.channel = proxy.channel
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "peerAdded":
+ assert len(args) == 1
+ _peer = Peer(self.channel.getRemotePeer(), args[0])
+ if self.proxy.peers.get(_peer.getID()):
+ protocol.log("Invalid peerAdded event", Exception())
+ return
+ self.proxy.peers[_peer.getID()] = _peer
+ for l in self.proxy.listeners:
+ try:
+ l.peerAdded(_peer)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerChanged":
+ assert len(args) == 1
+ m = args[0]
+ if not m: raise Exception("Locator service: invalid peerChanged event - no peer ID")
+ _peer = self.proxy.peers.get(m.get(peer.ATTR_ID))
+ if not _peer: return
+ self.proxy.peers[_peer.getID()] = _peer
+ for l in self.proxy.listeners:
+ try:
+ l.peerChanged(_peer)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerRemoved":
+ assert len(args) == 1
+ id = args[0]
+ _peer = self.proxy.peers.get(id)
+ if not _peer: return
+ del self.proxy.peers[id]
+ for l in self.proxy.listeners:
+ try:
+ l.peerRemoved(id)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ elif name == "peerHeartBeat":
+ assert len(args) == 1
+ id = args[0]
+ _peer = self.proxy.peers.get(id)
+ if not _peer: return
+ for l in self.proxy.listeners:
+ try:
+ l.peerHeartBeat(id)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ else:
+ raise IOError("Locator service: unknown event: " + name)
+ except Exception as x:
+ self.channel.terminate(x)
+
+class LocatorProxy(locator.LocatorService):
+ def __init__(self, channel):
+ self.channel = channel;
+ self.peers = {}
+ self.listeners = []
+ self.get_peers_done = False
+ self.event_listener = ChannelEventListener(self)
+ channel.addEventListener(self, self.event_listener)
+
+ def getPeers(self):
+ return self.peers
+
+ def redirect(self, _peer, done):
+ done = self._makeCallback(done)
+ service = self
+ class RedirectCommand(Command):
+ def __init__(self):
+ super(RedirectCommand, self).__init__(service.channel, service, "redirect", [_peer])
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneRedirect(self.token, error)
+ return RedirectCommand().token
+
+ def sync(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class SyncCommand(Command):
+ def __init__(self):
+ super(SyncCommand, self).__init__(service.channel, service, "sync", None)
+ def done(self, error, args):
+ if error: service.channel.terminate(error)
+ done.doneSync(self.token)
+ return SyncCommand().token
+
+ def addListener(self, listener):
+ self.listeners.append(listener)
+ if not self.get_peers_done:
+ service = self
+ class GetPeersCommand(Command):
+ def __init__(self):
+ super(GetPeersCommand, self).__init__(service.channel, service, "getPeers", None)
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if error:
+ protocol.log("Locator error", error)
+ return
+ c = args[1]
+ if c:
+ for m in c:
+ id = m.get(peer.ATTR_ID)
+ if service.peers.get(id): continue;
+ _peer = Peer(service.channel.getRemotePeer(), m)
+ service.peers[id] = _peer
+ for l in service.listeners:
+ try:
+ l.peerAdded(_peer)
+ except Exception as x:
+ protocol.log("Unhandled exception in Locator listener", x)
+ GetPeersCommand()
+ self.get_peers_done = True
+
+ def removeListener(self, listener):
+ self.listeners.remove(listener)
diff --git a/python/src/tcf/services/remote/MemoryMapProxy.py b/python/src/tcf/services/remote/MemoryMapProxy.py
index 8bf153bac..34aab1d5f 100644
--- a/python/src/tcf/services/remote/MemoryMapProxy.py
+++ b/python/src/tcf/services/remote/MemoryMapProxy.py
@@ -1,82 +1,82 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import memorymap
-from tcf.channel.Command import Command
-
-class MemoryMapProxy(memorymap.MemoryMapService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def get(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetCommand(Command):
- def __init__(self):
- super(GetCommand, self).__init__(service.channel, service, "get", (id,))
- def done(self, error, args):
- map = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: map = _toMemoryMap(args[1])
- done.doneGet(self.token, error, map)
- return GetCommand().token
-
- def set(self, id, map, done):
- if isinstance(map, memorymap.MemoryRegion) or isinstance(map, dict):
- map = (map,)
- done = self._makeCallback(done)
- service = self
- class SetCommand(Command):
- def __init__(self):
- super(SetCommand, self).__init__(service.channel, service, "set", (id, map))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneSet(self.token, error)
- return SetCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.pop(listener, None)
- if l: self.channel.removeEventListener(self, l)
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "changed":
- assert len(args) == 1
- self.listener.changed(args[0])
- else:
- raise IOError("MemoryMap service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
-
-
-def _toMemoryMap(o):
- if o is None: return None
- return map(_toMemoryRegion, o)
-
-def _toMemoryRegion(o):
- if o is None: return None
- return memorymap.MemoryRegion(o)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import memorymap
+from tcf.channel.Command import Command
+
+class MemoryMapProxy(memorymap.MemoryMapService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def get(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetCommand(Command):
+ def __init__(self):
+ super(GetCommand, self).__init__(service.channel, service, "get", (id,))
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: map = _toMemoryMap(args[1])
+ done.doneGet(self.token, error, map)
+ return GetCommand().token
+
+ def set(self, id, map, done):
+ if isinstance(map, memorymap.MemoryRegion) or isinstance(map, dict):
+ map = (map,)
+ done = self._makeCallback(done)
+ service = self
+ class SetCommand(Command):
+ def __init__(self):
+ super(SetCommand, self).__init__(service.channel, service, "set", (id, map))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.pop(listener, None)
+ if l: self.channel.removeEventListener(self, l)
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "changed":
+ assert len(args) == 1
+ self.listener.changed(args[0])
+ else:
+ raise IOError("MemoryMap service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
+
+
+def _toMemoryMap(o):
+ if o is None: return None
+ return map(_toMemoryRegion, o)
+
+def _toMemoryRegion(o):
+ if o is None: return None
+ return memorymap.MemoryRegion(o)
diff --git a/python/src/tcf/services/remote/MemoryProxy.py b/python/src/tcf/services/remote/MemoryProxy.py
index ebf8a2420..62f01bdcf 100644
--- a/python/src/tcf/services/remote/MemoryProxy.py
+++ b/python/src/tcf/services/remote/MemoryProxy.py
@@ -1,242 +1,242 @@
-# *******************************************************************************
-# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import errors, channel
-from tcf.services import memory
-from tcf.channel.Command import Command
-
-class Range(object):
- offs = 0
- size = 0
- stat = 0
- msg = None
- def __cmp__(self, o):
- if self.offs < o.offs: return -1
- if self.offs > o.offs: return +1
- return 0
-
-class MemoryErrorReport(errors.ErrorReport, memory.MemoryError, memory.ErrorOffset):
- def __init__(self, msg, attrs, addr, ranges):
- super(MemoryErrorReport, self).__init__(msg, attrs)
- if ranges is None:
- self.ranges = None
- else:
- self.ranges = []
- for m in ranges:
- r = Range()
- x = m.get(memory.ErrorOffset.RANGE_KEY_ADDR)
- if isinstance(x, str):
- y = int(x)
- else:
- y = x
- r.offs = y - addr
- r.size = m.get(memory.ErrorOffset.RANGE_KEY_SIZE)
- r.stat = m.get(memory.ErrorOffset.RANGE_KEY_STAT)
- r.msg = errors.toErrorString(m.get(memory.ErrorOffset.RANGE_KEY_MSG))
- assert r.offs >= 0
- assert r.size >= 0
- self.ranges.append(r)
- self.ranges.sort()
-
- def getMessage(self, offset):
- if self.ranges is None: return None
- l = 0
- h = len(self.ranges) - 1
- while l <= h:
- n = (l + h) / 2
- r = self.ranges[n]
- if r.offs > offset:
- h = n - 1
- elif offset >= r.offs + r.size:
- l = n + 1
- else:
- return r.msg
- return None
-
- def getStatus(self, offset):
- if self.ranges is None: return memory.ErrorOffset.BYTE_UNKNOWN
- l = 0
- h = len(self.ranges) - 1
- while l <= h:
- n = (l + h) / 2
- r = self.ranges[n]
- if r.offs > offset:
- h = n - 1
- elif offset >= r.offs + r.size:
- l = n + 1
- else:
- return r.stat
- return memory.ErrorOffset.BYTE_UNKNOWN
-
-
-class MemContext(memory.MemoryContext):
- def __init__(self, service, props):
- super(MemContext, self).__init__(props)
- self.service = service
-
- def fill(self, addr, word_size, value, size, mode, done):
- service = self.service
- id = self.getID()
- done = service._makeCallback(done)
- class FillCommand(MemoryCommand):
- def __init__(self):
- super(FillCommand, self).__init__(service,
- "fill", (id, addr, word_size, size, mode, value))
- def done(self, error, args):
- e = None
- if error:
- e = memory.MemoryError(error.message)
- else:
- assert len(args) == 2
- e = self.toMemoryError(args[0], args[1])
- done.doneMemory(self.token, e)
- return FillCommand().token
-
- def get(self, addr, word_size, buf, offs, size, mode, done):
- service = self.service
- id = self.getID()
- done = service._makeCallback(done)
- class GetCommand(MemoryCommand):
- def __init__(self):
- super(GetCommand, self).__init__(service,
- "get", (id, addr, word_size, size, mode))
- def done(self, error, args):
- e = None
- if error:
- e = memory.MemoryError(error.message)
- else:
- assert len(args) == 3
- bytes = channel.toByteArray(args[0])
- assert len(bytes) <= size
- buf[offs:offs+len(bytes)] = bytes
- e = self.toMemoryError(args[1], args[2])
- done.doneMemory(self.token, e)
- return GetCommand().token
-
- def set(self, addr, word_size, buf, offs, size, mode, done):
- service = self.service
- id = self.getID()
- done = service._makeCallback(done)
- class SetCommand(MemoryCommand):
- def __init__(self):
- super(SetCommand, self).__init__(service,
- "set", (id, addr, word_size, size, mode, bytearray(buf[offs:offs:size])))
- def done(self, error, args):
- e = None
- if error:
- e = memory.MemoryError(error.message)
- else:
- assert len(args) == 2
- e = self.toMemoryError(args[1], args[2])
- done.doneMemory(self.token, e)
- return SetCommand().token
-
-class MemoryProxy(memory.MemoryService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def getContext(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = MemContext(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
-
-class MemoryCommand(Command):
- def __init__(self, service, cmd, args):
- super(MemoryCommand, self).__init__(service.channel, service, cmd, args)
- def toMemoryError(self, addr, data, ranges):
- if data is None: return None
- code = data.get(errors.ERROR_CODE)
- cmd = self.getCommandString()
- if len(cmd) > 72: cmd = cmd[0:72] + "..."
- e = MemoryErrorReport(
- "TCF command exception:\nCommand: %s\nException: %s\nError code: " % (
- cmd, self.toErrorString(data), code),
- map, addr, ranges)
- caused_by = data.get(errors.ERROR_CAUSED_BY)
- if caused_by is not None: e.caused_by = self.toError(caused_by, False)
- return e
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "contextAdded":
- assert len(args) == 1
- self.listener.contextAdded(_toContextArray(self.service, args[0]))
- elif name == "contextChanged":
- assert len(args) == 1
- self.listener.contextChanged(_toContextArray(self.service, args[0]))
- elif name == "contextRemoved":
- assert len(args) == 1
- self.listener.contextRemoved(args[0])
- elif name == "memoryChanged":
- assert len(args) == 2
- self.listener.memoryChanged(args[0], _toAddrArray(args[1]), _toSizeArray(args[1]))
- else:
- raise IOError("Memory service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
-
-
-def _toContextArray(svc, o):
- if o is None: return None
- ctx = []
- for m in o: ctx.append(MemContext(svc, m))
- return ctx
-
-def _toSizeArray(o):
- if o is None: return None
- return map(lambda m: m.get("size", 0), o)
-
-def _toAddrArray(o):
- if o is None: return None
- return map(lambda m: m.get("addr"), o)
+# *******************************************************************************
+# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import errors, channel
+from tcf.services import memory
+from tcf.channel.Command import Command
+
+class Range(object):
+ offs = 0
+ size = 0
+ stat = 0
+ msg = None
+ def __cmp__(self, o):
+ if self.offs < o.offs: return -1
+ if self.offs > o.offs: return +1
+ return 0
+
+class MemoryErrorReport(errors.ErrorReport, memory.MemoryError, memory.ErrorOffset):
+ def __init__(self, msg, attrs, addr, ranges):
+ super(MemoryErrorReport, self).__init__(msg, attrs)
+ if ranges is None:
+ self.ranges = None
+ else:
+ self.ranges = []
+ for m in ranges:
+ r = Range()
+ x = m.get(memory.ErrorOffset.RANGE_KEY_ADDR)
+ if isinstance(x, str):
+ y = int(x)
+ else:
+ y = x
+ r.offs = y - addr
+ r.size = m.get(memory.ErrorOffset.RANGE_KEY_SIZE)
+ r.stat = m.get(memory.ErrorOffset.RANGE_KEY_STAT)
+ r.msg = errors.toErrorString(m.get(memory.ErrorOffset.RANGE_KEY_MSG))
+ assert r.offs >= 0
+ assert r.size >= 0
+ self.ranges.append(r)
+ self.ranges.sort()
+
+ def getMessage(self, offset):
+ if self.ranges is None: return None
+ l = 0
+ h = len(self.ranges) - 1
+ while l <= h:
+ n = (l + h) / 2
+ r = self.ranges[n]
+ if r.offs > offset:
+ h = n - 1
+ elif offset >= r.offs + r.size:
+ l = n + 1
+ else:
+ return r.msg
+ return None
+
+ def getStatus(self, offset):
+ if self.ranges is None: return memory.ErrorOffset.BYTE_UNKNOWN
+ l = 0
+ h = len(self.ranges) - 1
+ while l <= h:
+ n = (l + h) / 2
+ r = self.ranges[n]
+ if r.offs > offset:
+ h = n - 1
+ elif offset >= r.offs + r.size:
+ l = n + 1
+ else:
+ return r.stat
+ return memory.ErrorOffset.BYTE_UNKNOWN
+
+
+class MemContext(memory.MemoryContext):
+ def __init__(self, service, props):
+ super(MemContext, self).__init__(props)
+ self.service = service
+
+ def fill(self, addr, word_size, value, size, mode, done):
+ service = self.service
+ id = self.getID()
+ done = service._makeCallback(done)
+ class FillCommand(MemoryCommand):
+ def __init__(self):
+ super(FillCommand, self).__init__(service,
+ "fill", (id, addr, word_size, size, mode, value))
+ def done(self, error, args):
+ e = None
+ if error:
+ e = memory.MemoryError(error.message)
+ else:
+ assert len(args) == 2
+ e = self.toMemoryError(args[0], args[1])
+ done.doneMemory(self.token, e)
+ return FillCommand().token
+
+ def get(self, addr, word_size, buf, offs, size, mode, done):
+ service = self.service
+ id = self.getID()
+ done = service._makeCallback(done)
+ class GetCommand(MemoryCommand):
+ def __init__(self):
+ super(GetCommand, self).__init__(service,
+ "get", (id, addr, word_size, size, mode))
+ def done(self, error, args):
+ e = None
+ if error:
+ e = memory.MemoryError(error.message)
+ else:
+ assert len(args) == 3
+ bytes = channel.toByteArray(args[0])
+ assert len(bytes) <= size
+ buf[offs:offs+len(bytes)] = bytes
+ e = self.toMemoryError(args[1], args[2])
+ done.doneMemory(self.token, e)
+ return GetCommand().token
+
+ def set(self, addr, word_size, buf, offs, size, mode, done):
+ service = self.service
+ id = self.getID()
+ done = service._makeCallback(done)
+ class SetCommand(MemoryCommand):
+ def __init__(self):
+ super(SetCommand, self).__init__(service,
+ "set", (id, addr, word_size, size, mode, bytearray(buf[offs:offs:size])))
+ def done(self, error, args):
+ e = None
+ if error:
+ e = memory.MemoryError(error.message)
+ else:
+ assert len(args) == 2
+ e = self.toMemoryError(args[1], args[2])
+ done.doneMemory(self.token, e)
+ return SetCommand().token
+
+class MemoryProxy(memory.MemoryService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def getContext(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = MemContext(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+class MemoryCommand(Command):
+ def __init__(self, service, cmd, args):
+ super(MemoryCommand, self).__init__(service.channel, service, cmd, args)
+ def toMemoryError(self, addr, data, ranges):
+ if data is None: return None
+ code = data.get(errors.ERROR_CODE)
+ cmd = self.getCommandString()
+ if len(cmd) > 72: cmd = cmd[0:72] + "..."
+ e = MemoryErrorReport(
+ "TCF command exception:\nCommand: %s\nException: %s\nError code: " % (
+ cmd, self.toErrorString(data), code),
+ map, addr, ranges)
+ caused_by = data.get(errors.ERROR_CAUSED_BY)
+ if caused_by is not None: e.caused_by = self.toError(caused_by, False)
+ return e
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "contextAdded":
+ assert len(args) == 1
+ self.listener.contextAdded(_toContextArray(self.service, args[0]))
+ elif name == "contextChanged":
+ assert len(args) == 1
+ self.listener.contextChanged(_toContextArray(self.service, args[0]))
+ elif name == "contextRemoved":
+ assert len(args) == 1
+ self.listener.contextRemoved(args[0])
+ elif name == "memoryChanged":
+ assert len(args) == 2
+ self.listener.memoryChanged(args[0], _toAddrArray(args[1]), _toSizeArray(args[1]))
+ else:
+ raise IOError("Memory service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
+
+
+def _toContextArray(svc, o):
+ if o is None: return None
+ ctx = []
+ for m in o: ctx.append(MemContext(svc, m))
+ return ctx
+
+def _toSizeArray(o):
+ if o is None: return None
+ return map(lambda m: m.get("size", 0), o)
+
+def _toAddrArray(o):
+ if o is None: return None
+ return map(lambda m: m.get("addr"), o)
diff --git a/python/src/tcf/services/remote/PathMapProxy.py b/python/src/tcf/services/remote/PathMapProxy.py
index 93e8c07b8..770e972f9 100644
--- a/python/src/tcf/services/remote/PathMapProxy.py
+++ b/python/src/tcf/services/remote/PathMapProxy.py
@@ -1,56 +1,56 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import pathmap
-from tcf.channel.Command import Command
-
-class PathMapProxy(pathmap.PathMapService):
- def __init__(self, channel):
- self.channel = channel
-
- def get(self, done):
- done = self._makeCallback(done)
- service = self
- class GetCommand(Command):
- def __init__(self):
- super(GetCommand, self).__init__(service.channel, service, "get", None)
- def done(self, error, args):
- map = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: map = _toPathMap(args[1])
- done.doneGet(self.token, error, map)
- return GetCommand().token
-
- def set(self, map, done):
- if isinstance(map, pathmap.PathMapRule) or isinstance(map, dict):
- map = (map,)
- done = self._makeCallback(done)
- service = self
- class SetCommand(Command):
- def __init__(self):
- super(SetCommand, self).__init__(service.channel, service, "set", (map,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneSet(self.token, error)
- return SetCommand().token
-
-
-def _toPathMap(o):
- if o is None: return None
- return map(_toPathMapRule, o)
-
-def _toPathMapRule(o):
- if o is None: return None
- return pathmap.PathMapRule(o)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import pathmap
+from tcf.channel.Command import Command
+
+class PathMapProxy(pathmap.PathMapService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def get(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetCommand(Command):
+ def __init__(self):
+ super(GetCommand, self).__init__(service.channel, service, "get", None)
+ def done(self, error, args):
+ map = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: map = _toPathMap(args[1])
+ done.doneGet(self.token, error, map)
+ return GetCommand().token
+
+ def set(self, map, done):
+ if isinstance(map, pathmap.PathMapRule) or isinstance(map, dict):
+ map = (map,)
+ done = self._makeCallback(done)
+ service = self
+ class SetCommand(Command):
+ def __init__(self):
+ super(SetCommand, self).__init__(service.channel, service, "set", (map,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetCommand().token
+
+
+def _toPathMap(o):
+ if o is None: return None
+ return map(_toPathMapRule, o)
+
+def _toPathMapRule(o):
+ if o is None: return None
+ return pathmap.PathMapRule(o)
diff --git a/python/src/tcf/services/remote/ProcessesProxy.py b/python/src/tcf/services/remote/ProcessesProxy.py
index 4e1dff2c6..9cfdcbd56 100644
--- a/python/src/tcf/services/remote/ProcessesProxy.py
+++ b/python/src/tcf/services/remote/ProcessesProxy.py
@@ -1,215 +1,215 @@
-# *******************************************************************************
-# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import processes
-from tcf.channel.Command import Command
-
-class ProcessContext(processes.ProcessContext):
- def __init__(self, service, props):
- super(ProcessContext, self).__init__(props)
- self.service = service
-
- def attach(self, done):
- return self._command("attach", done)
-
- def detach(self, done):
- return self._command("detach", done)
-
- def terminate(self, done):
- return self._command("terminate", done)
-
- def _command(self, command, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- class _Command(Command):
- def __init__(self):
- super(_Command, self).__init__(service.channel, service,
- command, (id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return _Command().token
-
-class ProcessesProxy(processes.ProcessesService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def getChildren(self, parent_context_id, attached_only, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service,
- "getChildren", (parent_context_id, attached_only))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def getContext(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = ProcessContext(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getEnvironment(self, done):
- done = self._makeCallback(done)
- service = self
- class GetEnvCommand(Command):
- def __init__(self):
- super(GetEnvCommand, self).__init__(service.channel, service, "getEnvironment", None)
- def done(self, error, args):
- env = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- env = _toEnvMap(args[1])
- done.doneGetEnvironment(self.token, error, env)
- return GetEnvCommand().token
-
- def start(self, directory, file, command_line, environment, attach, done):
- done = self._makeCallback(done)
- service = self
- env = _toEnvStringArray(environment)
- class StartCommand(Command):
- def __init__(self):
- super(StartCommand, self).__init__(service.channel, service,
- "start", (directory, file, command_line, env, attach))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = ProcessContext(service, args[1])
- done.doneStart(self.token, error, ctx)
- return StartCommand().token
-
- def getSignalList(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetSignalsCommand(Command):
- def __init__(self):
- super(GetSignalsCommand, self).__init__(service.channel, service,
- "getSignalList", (context_id,))
- def done(self, error, args):
- list = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- list = args[1]
- done.doneGetSignalList(self.token, error, list)
- return GetSignalsCommand().token
-
- def getSignalMask(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetSignalMaskCommand(Command):
- def __init__(self):
- super(GetSignalMaskCommand, self).__init__(service.channel, service,
- "getSignalMask", (context_id,))
- def done(self, error, args):
- dont_stop = 0
- dont_pass = 0
- pending = 0
- if not error:
- assert len(args) == 4
- error = self.toError(args[0])
- dont_stop, dont_pass, pending = args[1:4]
- done.doneGetSignalMask(self.token, error, dont_stop, dont_pass, pending)
- return GetSignalMaskCommand().token
-
- def setSignalMask(self, context_id, dont_stop, dont_pass, done):
- done = self._makeCallback(done)
- service = self
- class SetSignalMaskCommand(Command):
- def __init__(self):
- super(SetSignalMaskCommand, self).__init__(service.channel, service,
- "setSignalMask", (context_id, dont_stop, dont_pass))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return SetSignalMaskCommand().token
-
- def signal(self, context_id, signal, done):
- done = self._makeCallback(done)
- service = self
- class SignalCommand(Command):
- def __init__(self):
- super(SignalCommand, self).__init__(service.channel, service,
- "signal", (context_id, signal))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return SignalCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "exited":
- assert len(args) == 2
- self.listener.exited(args[0], args[1])
- else:
- raise IOError("Processes service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
-
-def _toEnvStringArray(map):
- arr = []
- if not map: return arr
- for name, value in map.items():
- arr.append("%s=%s" % (name, value))
- return arr
-
-def _toEnvMap(arr):
- map = {}
- if not arr: return map
- for str in arr:
- i = str.find('=')
- if i >= 0: map[str[:i]] = str[i + 1:]
- else: map[str] = ""
- return map
+# *******************************************************************************
+# * Copyright (c) 2011, 2012 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import processes
+from tcf.channel.Command import Command
+
+class ProcessContext(processes.ProcessContext):
+ def __init__(self, service, props):
+ super(ProcessContext, self).__init__(props)
+ self.service = service
+
+ def attach(self, done):
+ return self._command("attach", done)
+
+ def detach(self, done):
+ return self._command("detach", done)
+
+ def terminate(self, done):
+ return self._command("terminate", done)
+
+ def _command(self, command, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ class _Command(Command):
+ def __init__(self):
+ super(_Command, self).__init__(service.channel, service,
+ command, (id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return _Command().token
+
+class ProcessesProxy(processes.ProcessesService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def getChildren(self, parent_context_id, attached_only, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service,
+ "getChildren", (parent_context_id, attached_only))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = ProcessContext(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getEnvironment(self, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetEnvCommand(Command):
+ def __init__(self):
+ super(GetEnvCommand, self).__init__(service.channel, service, "getEnvironment", None)
+ def done(self, error, args):
+ env = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ env = _toEnvMap(args[1])
+ done.doneGetEnvironment(self.token, error, env)
+ return GetEnvCommand().token
+
+ def start(self, directory, file, command_line, environment, attach, done):
+ done = self._makeCallback(done)
+ service = self
+ env = _toEnvStringArray(environment)
+ class StartCommand(Command):
+ def __init__(self):
+ super(StartCommand, self).__init__(service.channel, service,
+ "start", (directory, file, command_line, env, attach))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = ProcessContext(service, args[1])
+ done.doneStart(self.token, error, ctx)
+ return StartCommand().token
+
+ def getSignalList(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetSignalsCommand(Command):
+ def __init__(self):
+ super(GetSignalsCommand, self).__init__(service.channel, service,
+ "getSignalList", (context_id,))
+ def done(self, error, args):
+ list = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ list = args[1]
+ done.doneGetSignalList(self.token, error, list)
+ return GetSignalsCommand().token
+
+ def getSignalMask(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetSignalMaskCommand(Command):
+ def __init__(self):
+ super(GetSignalMaskCommand, self).__init__(service.channel, service,
+ "getSignalMask", (context_id,))
+ def done(self, error, args):
+ dont_stop = 0
+ dont_pass = 0
+ pending = 0
+ if not error:
+ assert len(args) == 4
+ error = self.toError(args[0])
+ dont_stop, dont_pass, pending = args[1:4]
+ done.doneGetSignalMask(self.token, error, dont_stop, dont_pass, pending)
+ return GetSignalMaskCommand().token
+
+ def setSignalMask(self, context_id, dont_stop, dont_pass, done):
+ done = self._makeCallback(done)
+ service = self
+ class SetSignalMaskCommand(Command):
+ def __init__(self):
+ super(SetSignalMaskCommand, self).__init__(service.channel, service,
+ "setSignalMask", (context_id, dont_stop, dont_pass))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return SetSignalMaskCommand().token
+
+ def signal(self, context_id, signal, done):
+ done = self._makeCallback(done)
+ service = self
+ class SignalCommand(Command):
+ def __init__(self):
+ super(SignalCommand, self).__init__(service.channel, service,
+ "signal", (context_id, signal))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return SignalCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "exited":
+ assert len(args) == 2
+ self.listener.exited(args[0], args[1])
+ else:
+ raise IOError("Processes service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
+
+def _toEnvStringArray(map):
+ arr = []
+ if not map: return arr
+ for name, value in map.items():
+ arr.append("%s=%s" % (name, value))
+ return arr
+
+def _toEnvMap(arr):
+ map = {}
+ if not arr: return map
+ for str in arr:
+ i = str.find('=')
+ if i >= 0: map[str[:i]] = str[i + 1:]
+ else: map[str] = ""
+ return map
diff --git a/python/src/tcf/services/remote/ProcessesV1Proxy.py b/python/src/tcf/services/remote/ProcessesV1Proxy.py
index 5ebf28a3e..c16d15624 100644
--- a/python/src/tcf/services/remote/ProcessesV1Proxy.py
+++ b/python/src/tcf/services/remote/ProcessesV1Proxy.py
@@ -1,32 +1,32 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from . import ProcessesProxy
-from tcf.services import processes_v1
-from tcf.channel.Command import Command
-
-class ProcessesV1Proxy(ProcessesProxy.ProcessesProxy, processes_v1.ProcessesV1Service):
- def start(self, directory, file, command_line, environment, params, done):
- done = self._makeCallback(done)
- service = self
- env = ProcessesProxy._toEnvStringArray(environment)
- class StartCommand(Command):
- def __init__(self):
- super(StartCommand, self).__init__(service.channel, service,
- "start", (directory, file, command_line, env, params))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = ProcessesProxy.ProcessContext(service, args[1])
- done.doneStart(self.token, error, ctx)
- return StartCommand().token
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from . import ProcessesProxy
+from tcf.services import processes_v1
+from tcf.channel.Command import Command
+
+class ProcessesV1Proxy(ProcessesProxy.ProcessesProxy, processes_v1.ProcessesV1Service):
+ def start(self, directory, file, command_line, environment, params, done):
+ done = self._makeCallback(done)
+ service = self
+ env = ProcessesProxy._toEnvStringArray(environment)
+ class StartCommand(Command):
+ def __init__(self):
+ super(StartCommand, self).__init__(service.channel, service,
+ "start", (directory, file, command_line, env, params))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = ProcessesProxy.ProcessContext(service, args[1])
+ done.doneStart(self.token, error, ctx)
+ return StartCommand().token
diff --git a/python/src/tcf/services/remote/RegistersProxy.py b/python/src/tcf/services/remote/RegistersProxy.py
index f33eea147..fdf3d9ae8 100644
--- a/python/src/tcf/services/remote/RegistersProxy.py
+++ b/python/src/tcf/services/remote/RegistersProxy.py
@@ -1,176 +1,176 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import registers
-from tcf.channel import toByteArray
-from tcf.channel.Command import Command
-
-class Context(registers.RegistersContext):
- def __init__(self, service, props):
- super(Context, self).__init__(props)
- self.service = service
-
- def getNamedValues(self):
- return _toValuesArray(self._props.get(registers.PROP_VALUES))
-
- def get(self, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- class GetCommand(Command):
- def __init__(self):
- super(GetCommand, self).__init__(service.channel, service, "get", (id,))
- def done(self, error, args):
- val = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- val = toByteArray(args[1])
- done.doneGet(self.token, error, val)
- return GetCommand().token
-
- def set(self, value, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- binary = bytearray(value)
- class SetCommand(Command):
- def __init__(self):
- super(SetCommand, self).__init__(service.channel, service, "set", (id, binary))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneSet(self.token, error)
- return SetCommand().token
-
- def search(self, filter, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- class SearchCommand(Command):
- def __init__(self):
- super(SearchCommand, self).__init__(service.channel, service, "search", (id, filter))
- def done(self, error, args):
- paths = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- paths = args[1]
- done.doneSearch(self.token, error, paths)
- return SearchCommand().token
-
-class RegistersProxy(registers.RegistersService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def getContext(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = Context(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getm(self, locs, done):
- done = self._makeCallback(done)
- service = self
- class GetMCommand(Command):
- def __init__(self):
- super(GetMCommand, self).__init__(service.channel, service, "getm", (locs,))
- def done(self, error, args):
- val = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- val = toByteArray(args[1])
- done.doneGet(self.token, error, val)
- return GetMCommand().token
-
- def setm(self, locs, value, done):
- done = self._makeCallback(done)
- service = self
- binary = bytearray(value)
- class SetMCommand(Command):
- def __init__(self):
- super(SetMCommand, self).__init__(service.channel, service, "setm", (locs, binary))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneSet(self.token, error)
- return SetMCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
-
-class NamedValueInfo(registers.NamedValue):
- def __init__(self, m):
- desc = m.get("Description")
- name = m.get("Name")
- value = toByteArray(m.get("Value"))
- super(NamedValueInfo, self).__init__(value, name, desc)
-
-def _toValuesArray(o):
- if o is None: return None
- arr = []
- for m in o:
- arr.append(NamedValueInfo(m))
- return arr
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "contextChanged":
- self.listener.contextChanged()
- elif name == "registerChanged":
- assert len(args) == 1
- self.listener.registerChanged(args[0])
- else:
- raise IOError("Registers service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import registers
+from tcf.channel import toByteArray
+from tcf.channel.Command import Command
+
+class Context(registers.RegistersContext):
+ def __init__(self, service, props):
+ super(Context, self).__init__(props)
+ self.service = service
+
+ def getNamedValues(self):
+ return _toValuesArray(self._props.get(registers.PROP_VALUES))
+
+ def get(self, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ class GetCommand(Command):
+ def __init__(self):
+ super(GetCommand, self).__init__(service.channel, service, "get", (id,))
+ def done(self, error, args):
+ val = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ val = toByteArray(args[1])
+ done.doneGet(self.token, error, val)
+ return GetCommand().token
+
+ def set(self, value, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ binary = bytearray(value)
+ class SetCommand(Command):
+ def __init__(self):
+ super(SetCommand, self).__init__(service.channel, service, "set", (id, binary))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetCommand().token
+
+ def search(self, filter, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ class SearchCommand(Command):
+ def __init__(self):
+ super(SearchCommand, self).__init__(service.channel, service, "search", (id, filter))
+ def done(self, error, args):
+ paths = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ paths = args[1]
+ done.doneSearch(self.token, error, paths)
+ return SearchCommand().token
+
+class RegistersProxy(registers.RegistersService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = Context(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getm(self, locs, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetMCommand(Command):
+ def __init__(self):
+ super(GetMCommand, self).__init__(service.channel, service, "getm", (locs,))
+ def done(self, error, args):
+ val = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ val = toByteArray(args[1])
+ done.doneGet(self.token, error, val)
+ return GetMCommand().token
+
+ def setm(self, locs, value, done):
+ done = self._makeCallback(done)
+ service = self
+ binary = bytearray(value)
+ class SetMCommand(Command):
+ def __init__(self):
+ super(SetMCommand, self).__init__(service.channel, service, "setm", (locs, binary))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneSet(self.token, error)
+ return SetMCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+class NamedValueInfo(registers.NamedValue):
+ def __init__(self, m):
+ desc = m.get("Description")
+ name = m.get("Name")
+ value = toByteArray(m.get("Value"))
+ super(NamedValueInfo, self).__init__(value, name, desc)
+
+def _toValuesArray(o):
+ if o is None: return None
+ arr = []
+ for m in o:
+ arr.append(NamedValueInfo(m))
+ return arr
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "contextChanged":
+ self.listener.contextChanged()
+ elif name == "registerChanged":
+ assert len(args) == 1
+ self.listener.registerChanged(args[0])
+ else:
+ raise IOError("Registers service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
diff --git a/python/src/tcf/services/remote/RunControlProxy.py b/python/src/tcf/services/remote/RunControlProxy.py
index 8c2832cf4..60d20fea8 100644
--- a/python/src/tcf/services/remote/RunControlProxy.py
+++ b/python/src/tcf/services/remote/RunControlProxy.py
@@ -1,158 +1,158 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import runcontrol
-from tcf.channel.Command import Command
-
-class RunContext(runcontrol.RunControlContext):
- def __init__(self, service, props):
- super(RunContext, self).__init__(props)
- self.service = service
-
- def getState(self, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- class GetStateCommand(Command):
- def __init__(self):
- super(GetStateCommand, self).__init__(service.channel, service, "getState", (id,))
- def done(self, error, args):
- susp = False
- pc = None
- reason = None
- map = None
- if not error:
- assert len(args) == 5
- error = self.toError(args[0])
- susp = args[1]
- if args[2]: pc = str(args[2])
- reason = args[3]
- map = args[4]
- done.doneGetState(self.token, error, susp, pc, reason, map)
- return GetStateCommand().token
-
-# def resume(self, mode, count, done):
-# return self._command("resume", [self.getID(), mode, count], done)
-
- def resume(self, mode, count, params, done):
- if not params:
- return self._command("resume", (self.getID(), mode, count), done)
- else:
- return self._command("resume", (self.getID(), mode, count, params), done)
-
- def suspend(self, done):
- return self._command("suspend", (self.getID(),), done)
-
- def terminate(self, done):
- return self._command("terminate", (self.getID(),), done)
-
- def _command(self, cmd, args, done):
- service = self.service
- done = service._makeCallback(done)
- class RCCommand(Command):
- def __init__(self, cmd, args):
- super(RCCommand, self).__init__(service.channel, service, cmd, args)
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return RCCommand(cmd, args).token
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "contextSuspended":
- assert len(args) == 4
- self.listener.contextSuspended(args[0], args[1], args[2], args[3])
- elif name == "contextResumed":
- assert len(args) == 1
- self.listener.contextResumed(args[0])
- elif name == "contextAdded":
- assert len(args) == 1
- self.listener.contextAdded(_toContextArray(self.service,args[0]))
- elif name == "contextChanged":
- assert len(args) == 1
- self.listener.contextChanged(_toContextArray(self.service,args[0]))
- elif name == "contextRemoved":
- assert len(args) == 1
- self.listener.contextRemoved(args[0])
- elif name == "contextException":
- assert len(args) == 2
- self.listener.contextException(args[0], args[1])
- elif name == "containerSuspended":
- assert len(args) == 5
- self.listener.containerSuspended(args[0], args[1], args[2], args[3], args[4])
- elif name == "containerResumed":
- assert len(args) == 1
- self.listener.containerResumed(args[0])
- else:
- raise IOError("RunControl service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
-
-class RunControlProxy(runcontrol.RunControlService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def addListener(self, listener):
- l = ChannelEventListener(self, listener)
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.get(listener)
- if l:
- del self.listeners[listener]
- self.channel.removeEventListener(self, l)
-
- def getContext(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = RunContext(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
-def _toContextArray(svc,o):
- if o is None: return None
- ctx = []
- for m in o: ctx.append(RunContext(svc,m))
- return ctx
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import runcontrol
+from tcf.channel.Command import Command
+
+class RunContext(runcontrol.RunControlContext):
+ def __init__(self, service, props):
+ super(RunContext, self).__init__(props)
+ self.service = service
+
+ def getState(self, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ class GetStateCommand(Command):
+ def __init__(self):
+ super(GetStateCommand, self).__init__(service.channel, service, "getState", (id,))
+ def done(self, error, args):
+ susp = False
+ pc = None
+ reason = None
+ map = None
+ if not error:
+ assert len(args) == 5
+ error = self.toError(args[0])
+ susp = args[1]
+ if args[2]: pc = str(args[2])
+ reason = args[3]
+ map = args[4]
+ done.doneGetState(self.token, error, susp, pc, reason, map)
+ return GetStateCommand().token
+
+# def resume(self, mode, count, done):
+# return self._command("resume", [self.getID(), mode, count], done)
+
+ def resume(self, mode, count, params, done):
+ if not params:
+ return self._command("resume", (self.getID(), mode, count), done)
+ else:
+ return self._command("resume", (self.getID(), mode, count, params), done)
+
+ def suspend(self, done):
+ return self._command("suspend", (self.getID(),), done)
+
+ def terminate(self, done):
+ return self._command("terminate", (self.getID(),), done)
+
+ def _command(self, cmd, args, done):
+ service = self.service
+ done = service._makeCallback(done)
+ class RCCommand(Command):
+ def __init__(self, cmd, args):
+ super(RCCommand, self).__init__(service.channel, service, cmd, args)
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return RCCommand(cmd, args).token
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "contextSuspended":
+ assert len(args) == 4
+ self.listener.contextSuspended(args[0], args[1], args[2], args[3])
+ elif name == "contextResumed":
+ assert len(args) == 1
+ self.listener.contextResumed(args[0])
+ elif name == "contextAdded":
+ assert len(args) == 1
+ self.listener.contextAdded(_toContextArray(self.service,args[0]))
+ elif name == "contextChanged":
+ assert len(args) == 1
+ self.listener.contextChanged(_toContextArray(self.service,args[0]))
+ elif name == "contextRemoved":
+ assert len(args) == 1
+ self.listener.contextRemoved(args[0])
+ elif name == "contextException":
+ assert len(args) == 2
+ self.listener.contextException(args[0], args[1])
+ elif name == "containerSuspended":
+ assert len(args) == 5
+ self.listener.containerSuspended(args[0], args[1], args[2], args[3], args[4])
+ elif name == "containerResumed":
+ assert len(args) == 1
+ self.listener.containerResumed(args[0])
+ else:
+ raise IOError("RunControl service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
+
+class RunControlProxy(runcontrol.RunControlService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def addListener(self, listener):
+ l = ChannelEventListener(self, listener)
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.get(listener)
+ if l:
+ del self.listeners[listener]
+ self.channel.removeEventListener(self, l)
+
+ def getContext(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (context_id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = RunContext(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+def _toContextArray(svc,o):
+ if o is None: return None
+ ctx = []
+ for m in o: ctx.append(RunContext(svc,m))
+ return ctx
diff --git a/python/src/tcf/services/remote/StackTraceProxy.py b/python/src/tcf/services/remote/StackTraceProxy.py
index b551af36f..5a2d6288f 100644
--- a/python/src/tcf/services/remote/StackTraceProxy.py
+++ b/python/src/tcf/services/remote/StackTraceProxy.py
@@ -1,54 +1,54 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import stacktrace
-from tcf.channel.Command import Command
-
-class StackTraceProxy(stacktrace.StackTraceService):
- def __init__(self, channel):
- self.channel = channel
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def getContext(self, ids, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (ids,))
- def done(self, error, args):
- ctxs = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[1])
- ctxs = service.toContextArray(args[0])
- done.doneGetContext(self.token, error, ctxs)
- return GetContextCommand().token
-
- def toContextArray(self, ctxProps):
- if ctxProps is None: return None
- ctxs = []
- for props in ctxProps:
- ctxs.append(stacktrace.StackTraceContext(props))
- return ctxs
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import stacktrace
+from tcf.channel.Command import Command
+
+class StackTraceProxy(stacktrace.StackTraceService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, ids, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (ids,))
+ def done(self, error, args):
+ ctxs = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[1])
+ ctxs = service.toContextArray(args[0])
+ done.doneGetContext(self.token, error, ctxs)
+ return GetContextCommand().token
+
+ def toContextArray(self, ctxProps):
+ if ctxProps is None: return None
+ ctxs = []
+ for props in ctxProps:
+ ctxs.append(stacktrace.StackTraceContext(props))
+ return ctxs
diff --git a/python/src/tcf/services/remote/StreamsProxy.py b/python/src/tcf/services/remote/StreamsProxy.py
index d4149099d..67297e7d1 100644
--- a/python/src/tcf/services/remote/StreamsProxy.py
+++ b/python/src/tcf/services/remote/StreamsProxy.py
@@ -1,146 +1,146 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import streams
-from tcf import channel
-from tcf.channel.Command import Command
-
-class StreamsProxy(streams.StreamsService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def connect(self, stream_id, done):
- done = self._makeCallback(done)
- service = self
- class ConnectCommand(Command):
- def __init__(self):
- super(ConnectCommand, self).__init__(service.channel, service, "connect", (stream_id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneConnect(self.token, error)
- return ConnectCommand().token
-
- def disconnect(self, stream_id, done):
- done = self._makeCallback(done)
- service = self
- class DisconnectCommand(Command):
- def __init__(self):
- super(DisconnectCommand, self).__init__(service.channel, service, "disconnect", (stream_id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneDisconnect(self.token, error)
- return DisconnectCommand().token
-
- def eos(self, stream_id, done):
- done = self._makeCallback(done)
- service = self
- class EOSCommand(Command):
- def __init__(self):
- super(EOSCommand, self).__init__(service.channel, service, "eos", (stream_id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneEOS(self.token, error)
- return EOSCommand().token
-
- def read(self, stream_id, size, done):
- done = self._makeCallback(done)
- service = self
- class ReadCommand(Command):
- def __init__(self):
- super(ReadCommand, self).__init__(service.channel, service, "read", (stream_id, size))
- def done(self, error, args):
- lost_size = 0
- data = None
- eos = False
- if not error:
- assert len(args) == 4
- data = channel.toByteArray(args[0])
- error = self.toError(args[1])
- lost_size = args[2]
- eos = args[3]
- done.doneRead(self.token, error, lost_size, data, eos)
- return ReadCommand().token
-
- def subscribe(self, stream_type, listener, done):
- done = self._makeCallback(done)
- service = self
- class SubscribeCommand(Command):
- def __init__(self):
- super(SubscribeCommand, self).__init__(service.channel, service, "subscribe", (stream_type,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- if not error:
- l = ChannelEventListener(service, listener)
- service.listeners[listener] = l
- service.channel.addEventListener(service, l)
- done.doneSubscribe(self.token, error)
- return SubscribeCommand().token
-
- def unsubscribe(self, stream_type, listener, done):
- done = self._makeCallback(done)
- service = self
- class UnsubscribeCommand(Command):
- def __init__(self):
- super(UnsubscribeCommand, self).__init__(service.channel, service, "unsubscribe", (stream_type,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- if not error:
- l = service.listeners.pop(listener, None)
- if l: service.channel.removeEventListener(service, l)
- done.doneUnsubscribe(self.token, error)
- return UnsubscribeCommand().token
-
- def write(self, stream_id, buf, offset, size, done):
- done = self._makeCallback(done)
- service = self
- binary = buf[offset:offset+size]
- class WriteCommand(Command):
- def __init__(self):
- super(WriteCommand, self).__init__(service.channel, service, "write", (stream_id, binary))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneWrite(self.token, error)
- return WriteCommand().token
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "created":
- if len(args) == 3:
- self.listener.created(args[0], args[1], args[2])
- else:
- assert len(args) == 2
- self.listener.created(args[0], args[1], None)
- elif name == "disposed":
- assert len(args) == 2
- self.listener.disposed(args[0], args[1])
- else:
- raise IOError("Streams service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import streams
+from tcf import channel
+from tcf.channel.Command import Command
+
+class StreamsProxy(streams.StreamsService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def connect(self, stream_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class ConnectCommand(Command):
+ def __init__(self):
+ super(ConnectCommand, self).__init__(service.channel, service, "connect", (stream_id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneConnect(self.token, error)
+ return ConnectCommand().token
+
+ def disconnect(self, stream_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class DisconnectCommand(Command):
+ def __init__(self):
+ super(DisconnectCommand, self).__init__(service.channel, service, "disconnect", (stream_id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneDisconnect(self.token, error)
+ return DisconnectCommand().token
+
+ def eos(self, stream_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class EOSCommand(Command):
+ def __init__(self):
+ super(EOSCommand, self).__init__(service.channel, service, "eos", (stream_id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneEOS(self.token, error)
+ return EOSCommand().token
+
+ def read(self, stream_id, size, done):
+ done = self._makeCallback(done)
+ service = self
+ class ReadCommand(Command):
+ def __init__(self):
+ super(ReadCommand, self).__init__(service.channel, service, "read", (stream_id, size))
+ def done(self, error, args):
+ lost_size = 0
+ data = None
+ eos = False
+ if not error:
+ assert len(args) == 4
+ data = channel.toByteArray(args[0])
+ error = self.toError(args[1])
+ lost_size = args[2]
+ eos = args[3]
+ done.doneRead(self.token, error, lost_size, data, eos)
+ return ReadCommand().token
+
+ def subscribe(self, stream_type, listener, done):
+ done = self._makeCallback(done)
+ service = self
+ class SubscribeCommand(Command):
+ def __init__(self):
+ super(SubscribeCommand, self).__init__(service.channel, service, "subscribe", (stream_type,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ if not error:
+ l = ChannelEventListener(service, listener)
+ service.listeners[listener] = l
+ service.channel.addEventListener(service, l)
+ done.doneSubscribe(self.token, error)
+ return SubscribeCommand().token
+
+ def unsubscribe(self, stream_type, listener, done):
+ done = self._makeCallback(done)
+ service = self
+ class UnsubscribeCommand(Command):
+ def __init__(self):
+ super(UnsubscribeCommand, self).__init__(service.channel, service, "unsubscribe", (stream_type,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ if not error:
+ l = service.listeners.pop(listener, None)
+ if l: service.channel.removeEventListener(service, l)
+ done.doneUnsubscribe(self.token, error)
+ return UnsubscribeCommand().token
+
+ def write(self, stream_id, buf, offset, size, done):
+ done = self._makeCallback(done)
+ service = self
+ binary = buf[offset:offset+size]
+ class WriteCommand(Command):
+ def __init__(self):
+ super(WriteCommand, self).__init__(service.channel, service, "write", (stream_id, binary))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneWrite(self.token, error)
+ return WriteCommand().token
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "created":
+ if len(args) == 3:
+ self.listener.created(args[0], args[1], args[2])
+ else:
+ assert len(args) == 2
+ self.listener.created(args[0], args[1], None)
+ elif name == "disposed":
+ assert len(args) == 2
+ self.listener.disposed(args[0], args[1])
+ else:
+ raise IOError("Streams service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
diff --git a/python/src/tcf/services/remote/SymbolsProxy.py b/python/src/tcf/services/remote/SymbolsProxy.py
index 7d911f6c9..72c3b10fb 100644
--- a/python/src/tcf/services/remote/SymbolsProxy.py
+++ b/python/src/tcf/services/remote/SymbolsProxy.py
@@ -1,121 +1,121 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import channel
-from tcf.services import symbols
-from tcf.channel.Command import Command
-
-
-class Context(symbols.Symbol):
- def __init__(self, props):
- super(Context, self).__init__(props)
- self.value = channel.toByteArray(props.get(symbols.PROP_VALUE))
-
- def getValue(self):
- return self.value
-
-
-class SymbolsProxy(symbols.SymbolsService):
- def __init__(self, channel):
- self.channel = channel
-
- def getContext(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = Context(args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def find(self, context_id, ip, name, done):
- done = self._makeCallback(done)
- service = self
- class FindCommand(Command):
- def __init__(self):
- super(FindCommand, self).__init__(service.channel, service, "find", (context_id, ip, name))
- def done(self, error, args):
- id = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- id = args[1]
- done.doneFind(self.token, error, id)
- return FindCommand().token
-
- def findByAddr(self, context_id, addr, done):
- done = self._makeCallback(done)
- service = self
- class FindByAddrCommand(Command):
- def __init__(self):
- super(FindByAddrCommand, self).__init__(service.channel, service, "findByAddr", (context_id, addr))
- def done(self, error, args):
- id = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- id = args[1]
- done.doneFind(self.token, error, id)
- return FindByAddrCommand().token
-
- def list(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class ListCommand(Command):
- def __init__(self):
- super(ListCommand, self).__init__(service.channel, service, "list", (context_id,))
- def done(self, error, args):
- lst = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- lst = args[1]
- done.doneList(self.token, error, lst)
- return ListCommand().token
-
- def findFrameInfo(self, context_id, address, done):
- done = self._makeCallback(done)
- service = self
- class FindFrameInfoCommand(Command):
- def __init__(self):
- super(FindFrameInfoCommand, self).__init__(service.channel, service, "findFrameInfo", (context_id, address))
- def done(self, error, args):
- address = None
- size = None
- fp_cmds = None
- reg_cmds = None
- if not error:
- assert len(args) == 5
- error = self.toError(args[0])
- address, size, fp_cmds, reg_cmds = args[1:5]
- done.doneFindFrameInfo(self.token, error, address, size, fp_cmds, reg_cmds)
- return FindFrameInfoCommand().token
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import channel
+from tcf.services import symbols
+from tcf.channel.Command import Command
+
+
+class Context(symbols.Symbol):
+ def __init__(self, props):
+ super(Context, self).__init__(props)
+ self.value = channel.toByteArray(props.get(symbols.PROP_VALUE))
+
+ def getValue(self):
+ return self.value
+
+
+class SymbolsProxy(symbols.SymbolsService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getContext(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = Context(args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def find(self, context_id, ip, name, done):
+ done = self._makeCallback(done)
+ service = self
+ class FindCommand(Command):
+ def __init__(self):
+ super(FindCommand, self).__init__(service.channel, service, "find", (context_id, ip, name))
+ def done(self, error, args):
+ id = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ id = args[1]
+ done.doneFind(self.token, error, id)
+ return FindCommand().token
+
+ def findByAddr(self, context_id, addr, done):
+ done = self._makeCallback(done)
+ service = self
+ class FindByAddrCommand(Command):
+ def __init__(self):
+ super(FindByAddrCommand, self).__init__(service.channel, service, "findByAddr", (context_id, addr))
+ def done(self, error, args):
+ id = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ id = args[1]
+ done.doneFind(self.token, error, id)
+ return FindByAddrCommand().token
+
+ def list(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class ListCommand(Command):
+ def __init__(self):
+ super(ListCommand, self).__init__(service.channel, service, "list", (context_id,))
+ def done(self, error, args):
+ lst = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ lst = args[1]
+ done.doneList(self.token, error, lst)
+ return ListCommand().token
+
+ def findFrameInfo(self, context_id, address, done):
+ done = self._makeCallback(done)
+ service = self
+ class FindFrameInfoCommand(Command):
+ def __init__(self):
+ super(FindFrameInfoCommand, self).__init__(service.channel, service, "findFrameInfo", (context_id, address))
+ def done(self, error, args):
+ address = None
+ size = None
+ fp_cmds = None
+ reg_cmds = None
+ if not error:
+ assert len(args) == 5
+ error = self.toError(args[0])
+ address, size, fp_cmds, reg_cmds = args[1:5]
+ done.doneFindFrameInfo(self.token, error, address, size, fp_cmds, reg_cmds)
+ return FindFrameInfoCommand().token
diff --git a/python/src/tcf/services/remote/SysMonitorProxy.py b/python/src/tcf/services/remote/SysMonitorProxy.py
index 04aad1969..bf1f16bd7 100644
--- a/python/src/tcf/services/remote/SysMonitorProxy.py
+++ b/python/src/tcf/services/remote/SysMonitorProxy.py
@@ -1,77 +1,77 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. self program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies self distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import sysmonitor
-from tcf.channel.Command import Command
-
-class SysMonitorProxy(sysmonitor.SysMonitorService):
- def __init__(self, channel):
- self.channel = channel
-
- def getChildren(self, parent_context_id, done):
- done = self._makeCallback(done)
- service = self
- class GetChildrenCommand(Command):
- def __init__(self):
- super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
- def done(self, error, args):
- contexts = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- contexts = args[1]
- done.doneGetChildren(self.token, error, contexts)
- return GetChildrenCommand().token
-
- def getContext(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = sysmonitor.SysMonitorContext(args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def getCommandLine(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetCommandLineCommand(Command):
- def __init__(self):
- super(GetCommandLineCommand, self).__init__(service.channel, service, "getCommandLine", (id,))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = args[1]
- done.doneGetCommandLine(self.token, error, arr)
- return GetCommandLineCommand().token
-
- def getEnvironment(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetEnvironmentCommand(Command):
- def __init__(self):
- super(GetEnvironmentCommand, self).__init__(service.channel, service, "getEnvironment", (id,))
- def done(self, error, args):
- arr = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- arr = args[1]
- done.doneGetCommandLine(self.token, error, arr)
- return GetEnvironmentCommand().token
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. self program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies self distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import sysmonitor
+from tcf.channel.Command import Command
+
+class SysMonitorProxy(sysmonitor.SysMonitorService):
+ def __init__(self, channel):
+ self.channel = channel
+
+ def getChildren(self, parent_context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetChildrenCommand(Command):
+ def __init__(self):
+ super(GetChildrenCommand, self).__init__(service.channel, service, "getChildren", (parent_context_id,))
+ def done(self, error, args):
+ contexts = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ contexts = args[1]
+ done.doneGetChildren(self.token, error, contexts)
+ return GetChildrenCommand().token
+
+ def getContext(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = sysmonitor.SysMonitorContext(args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def getCommandLine(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetCommandLineCommand(Command):
+ def __init__(self):
+ super(GetCommandLineCommand, self).__init__(service.channel, service, "getCommandLine", (id,))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = args[1]
+ done.doneGetCommandLine(self.token, error, arr)
+ return GetCommandLineCommand().token
+
+ def getEnvironment(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetEnvironmentCommand(Command):
+ def __init__(self):
+ super(GetEnvironmentCommand, self).__init__(service.channel, service, "getEnvironment", (id,))
+ def done(self, error, args):
+ arr = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ arr = args[1]
+ done.doneGetCommandLine(self.token, error, arr)
+ return GetEnvironmentCommand().token
diff --git a/python/src/tcf/services/remote/TerminalsProxy.py b/python/src/tcf/services/remote/TerminalsProxy.py
index 5e68c3406..22217e27b 100644
--- a/python/src/tcf/services/remote/TerminalsProxy.py
+++ b/python/src/tcf/services/remote/TerminalsProxy.py
@@ -1,123 +1,123 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf.services import terminals
-from tcf import channel
-from tcf.channel.Command import Command
-
-class TerminalContext(terminals.TerminalContext):
- def __init__(self, service, props):
- super(TerminalContext, self).__init__(props)
- self.service = service
-
- def exit(self, done):
- service = self.service
- done = service._makeCallback(done)
- id = self.getID()
- class ExitCommand(Command):
- def __init__(self, cmd, args):
- super(ExitCommand, self).__init__(service.channel, service, "exit", id)
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return ExitCommand().token
-
-
-class TerminalsProxy(terminals.TerminalsService):
- def __init__(self, channel):
- self.channel = channel
- self.listeners = {}
-
- def getContext(self, id, done):
- done = self._makeCallback(done)
- service = self
- class GetContextCommand(Command):
- def __init__(self):
- super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = TerminalContext(service, args[1])
- done.doneGetContext(self.token, error, ctx)
- return GetContextCommand().token
-
- def launch(self, type, encoding, environment, done):
- done = self._makeCallback(done)
- service = self
- class LaunchCommand(Command):
- def __init__(self):
- super(LaunchCommand, self).__init__(service.channel, service, "launch", (type, encoding, environment))
- def done(self, error, args):
- ctx = None
- if not error:
- assert len(args) == 2
- error = self.toError(args[0])
- if args[1]: ctx = TerminalContext(service, args[1])
- done.doneLaunch(self.token, error, ctx)
- return LaunchCommand().token
-
- def setWinSize(self, context_id, newWidth, newHeight, done):
- done = self._makeCallback(done)
- service = self
- class SetWinSizeCommand(Command):
- def __init__(self):
- super(SetWinSizeCommand, self).__init__(service.channel, service, "setWinSize", (context_id, newWidth, newHeight))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return SetWinSizeCommand().token
-
- def exit(self, context_id, done):
- done = self._makeCallback(done)
- service = self
- class ExitCommand(Command):
- def __init__(self):
- super(ExitCommand, self).__init__(service.channel, service, "exit", (context_id,))
- def done(self, error, args):
- if not error:
- assert len(args) == 1
- error = self.toError(args[0])
- done.doneCommand(self.token, error)
- return ExitCommand().token
-
- def addListener(self, listener):
- l = ChannelEventListener()
- self.channel.addEventListener(self, l)
- self.listeners[listener] = l
-
- def removeListener(self, listener):
- l = self.listeners.pop(listener, None)
- if l: self.channel.removeEventListener(self, l)
-
-
-class ChannelEventListener(channel.EventListener):
- def __init__(self, service, listener):
- self.service = service
- self.listener = listener
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- if name == "exited":
- assert len(args) == 2
- self.listener.exited(args[0], args[1])
- elif name == "winSizeChanged":
- assert len(args) == 3
- self.listener.winSizeChanged(args[0], args[1], args[2])
- else:
- raise IOError("Terminals service: unknown event: " + name);
- except Exception as x:
- self.service.channel.terminate(x)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf.services import terminals
+from tcf import channel
+from tcf.channel.Command import Command
+
+class TerminalContext(terminals.TerminalContext):
+ def __init__(self, service, props):
+ super(TerminalContext, self).__init__(props)
+ self.service = service
+
+ def exit(self, done):
+ service = self.service
+ done = service._makeCallback(done)
+ id = self.getID()
+ class ExitCommand(Command):
+ def __init__(self, cmd, args):
+ super(ExitCommand, self).__init__(service.channel, service, "exit", id)
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return ExitCommand().token
+
+
+class TerminalsProxy(terminals.TerminalsService):
+ def __init__(self, channel):
+ self.channel = channel
+ self.listeners = {}
+
+ def getContext(self, id, done):
+ done = self._makeCallback(done)
+ service = self
+ class GetContextCommand(Command):
+ def __init__(self):
+ super(GetContextCommand, self).__init__(service.channel, service, "getContext", (id,))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = TerminalContext(service, args[1])
+ done.doneGetContext(self.token, error, ctx)
+ return GetContextCommand().token
+
+ def launch(self, type, encoding, environment, done):
+ done = self._makeCallback(done)
+ service = self
+ class LaunchCommand(Command):
+ def __init__(self):
+ super(LaunchCommand, self).__init__(service.channel, service, "launch", (type, encoding, environment))
+ def done(self, error, args):
+ ctx = None
+ if not error:
+ assert len(args) == 2
+ error = self.toError(args[0])
+ if args[1]: ctx = TerminalContext(service, args[1])
+ done.doneLaunch(self.token, error, ctx)
+ return LaunchCommand().token
+
+ def setWinSize(self, context_id, newWidth, newHeight, done):
+ done = self._makeCallback(done)
+ service = self
+ class SetWinSizeCommand(Command):
+ def __init__(self):
+ super(SetWinSizeCommand, self).__init__(service.channel, service, "setWinSize", (context_id, newWidth, newHeight))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return SetWinSizeCommand().token
+
+ def exit(self, context_id, done):
+ done = self._makeCallback(done)
+ service = self
+ class ExitCommand(Command):
+ def __init__(self):
+ super(ExitCommand, self).__init__(service.channel, service, "exit", (context_id,))
+ def done(self, error, args):
+ if not error:
+ assert len(args) == 1
+ error = self.toError(args[0])
+ done.doneCommand(self.token, error)
+ return ExitCommand().token
+
+ def addListener(self, listener):
+ l = ChannelEventListener()
+ self.channel.addEventListener(self, l)
+ self.listeners[listener] = l
+
+ def removeListener(self, listener):
+ l = self.listeners.pop(listener, None)
+ if l: self.channel.removeEventListener(self, l)
+
+
+class ChannelEventListener(channel.EventListener):
+ def __init__(self, service, listener):
+ self.service = service
+ self.listener = listener
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ if name == "exited":
+ assert len(args) == 2
+ self.listener.exited(args[0], args[1])
+ elif name == "winSizeChanged":
+ assert len(args) == 3
+ self.listener.winSizeChanged(args[0], args[1], args[2])
+ else:
+ raise IOError("Terminals service: unknown event: " + name);
+ except Exception as x:
+ self.service.channel.terminate(x)
diff --git a/python/src/tcf/services/runcontrol.py b/python/src/tcf/services/runcontrol.py
index d99010e1e..ac72e36e1 100644
--- a/python/src/tcf/services/runcontrol.py
+++ b/python/src/tcf/services/runcontrol.py
@@ -1,482 +1,482 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-from tcf import services
-
-NAME = "RunControl"
-
-# Context property names.
-# Run control context ID */
-PROP_ID = "ID"
-
-# Context parent (owner) ID, for a thread it is same as process ID */
-PROP_PARENT_ID = "ParentID"
-
-# Context process (memory space) ID */
-PROP_PROCESS_ID = "ProcessID"
-
-# ID of a context that created this context */
-PROP_CREATOR_ID = "CreatorID"
-
-# Human readable context name */
-PROP_NAME = "Name"
-
-# true if the context is a container. Container can propagate run control commands to his children */
-PROP_IS_CONTAINER = "IsContainer"
-
-# true if context has execution state - can be suspended/resumed */
-PROP_HAS_STATE = "HasState"
-
-# Bit-set of RM_ values that are supported by the context */
-PROP_CAN_RESUME = "CanResume"
-
-# Bit-set of RM_ values that can be used with count > 1 */
-PROP_CAN_COUNT = "CanCount"
-
-# true if suspend command is supported by the context */
-PROP_CAN_SUSPEND = "CanSuspend"
-
-# true if terminate command is supported by the context */
-PROP_CAN_TERMINATE = "CanTerminate"
-
-# Context ID of a run control group that contains the context.
-# Members of same group are always suspended and resumed together:
-# resuming/suspending a context resumes/suspends all members of the group */
-PROP_RC_GROUP = "RCGroup"
-
-# Context resume modes.
-RM_RESUME = 0
-
-# Step over a single instruction.
-# If the instruction is a function call then don't stop until the function returns.
-
-RM_STEP_OVER = 1
-
-# Step a single instruction.
-# If the instruction is a function call then stop at first instruction of the function.
-RM_STEP_INTO = 2
-
-# Step over a single source code line.
-# If the line contains a function call then don't stop until the function returns.
-RM_STEP_OVER_LINE = 3
-
-# Step a single source code line.
-# If the line contains a function call then stop at first line of the function.
-RM_STEP_INTO_LINE = 4
-
-# Run until control returns from current function.
-RM_STEP_OUT = 5
-
-# Start running backwards.
-# Execution will continue until suspended by command or breakpoint.
-RM_REVERSE_RESUME = 6
-
-# Reverse of RM_STEP_OVER - run backwards over a single instruction.
-# If the instruction is a function call then don't stop until get out of the function.
-RM_REVERSE_STEP_OVER = 7
-
-# Reverse of RM_STEP_INTO.
-# This effectively "un-executes" the previous instruction
-RM_REVERSE_STEP_INTO = 8
-
-# Reverse of RM_STEP_OVER_LINE.
-# Resume backward execution of given context until control reaches an instruction that belongs
-# to a different source line.
-# If the line contains a function call then don't stop until get out of the function.
-# Error is returned if line number information not available.
-RM_REVERSE_STEP_OVER_LINE = 9
-
-# Reverse of RM_STEP_INTO_LINE,
-# Resume backward execution of given context until control reaches an instruction that belongs
-# to a different line of source code.
-# If a function is called, stop at the beginning of the last line of the function code.
-# Error is returned if line number information not available.
-RM_REVERSE_STEP_INTO_LINE = 10
-
-# Reverse of RM_STEP_OUT.
-# Resume backward execution of the given context until control reaches the point where the current function was called.
-RM_REVERSE_STEP_OUT = 11
-
-# Step over instructions until PC is outside the specified range.
-# Any function call within the range is considered to be in range.
-RM_STEP_OVER_RANGE = 12
-
-# Step instruction until PC is outside the specified range for any reason.
-RM_STEP_INTO_RANGE = 13
-
-# Reverse of RM_STEP_OVER_RANGE
-RM_REVERSE_STEP_OVER_RANGE = 14
-
-# Reverse of RM_STEP_INTO_RANGE
-RM_REVERSE_STEP_INTO_RANGE = 15
-
-# Run until the context becomes active - scheduled to run on a target CPU
-RM_UNTIL_ACTIVE = 16
-
-# Run reverse until the context becomes active
-RM_REVERSE_UNTIL_ACTIVE = 17
-
-# State change reason of a context.
-# Reason can be any text, but if it is one of predefined strings,
-# a generic client might be able to handle it better.
-REASON_USER_REQUEST = "Suspended"
-REASON_STEP = "Step"
-REASON_BREAKPOINT = "Breakpoint"
-REASON_EXCEPTION = "Exception"
-REASON_CONTAINER = "Container"
-REASON_WATCHPOINT = "Watchpoint"
-REASON_SIGNAL = "Signal"
-REASON_SHAREDLIB = "Shared Library"
-REASON_ERROR = "Error"
-
-# Optional parameters of context state.
-STATE_SIGNAL = "Signal"
-STATE_SIGNAL_NAME = "SignalName"
-STATE_SIGNAL_DESCRIPTION = "SignalDescription"
-STATE_BREAKPOINT_IDS = "BPs"
-STATE_PC_ERROR = "PCError"
-
-# Optional parameters of resume command.
-# Integer - starting address of step range, inclusive */
-RP_RANGE_START = "RangeStart"
-
-# Integer - ending address of step range, exclusive */
-RP_RANGE_END = "RangeEnd"
-
-class RunControlService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context properties for given context ID.
-
- @param id - context ID.
- @param done - callback interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve children of given context.
-
- @param parent_context_id - parent context ID. Can be None -
- to retrieve top level of the hierarchy, or one of context IDs retrieved
- by previous getContext or getChildren commands.
- @param done - callback interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add run control event listener.
- @param listener - run control event listener to add.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove run control event listener.
- @param listener - run control event listener to remove.
- """
- raise NotImplementedError("Abstract method")
-
-
-class RunControlError(Exception):
- pass
-
-class DoneGetState(object):
- def doneGetState(self, token, error, suspended, pc, reason, params):
- """
- Called when getState command execution is complete.
- @param token - pending command handle.
- @param error - command execution error or None.
- @param suspended - true if the context is suspended
- @param pc - program counter of the context (if suspended).
- @param reason - suspend reason (if suspended), see REASON_*.
- @param params - additional target specific data about context state, see STATE_*.
- """
- pass
-
-class DoneCommand(object):
- def doneCommand(self, token, error):
- """
- Called when run control command execution is complete.
- @param token - pending command handle.
- @param error - command execution error or None.
- """
- pass
-
-class DoneGetContext(object):
- "Client callback interface for getContext()."
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneGetChildren(object):
- "Client callback interface for getChildren()."
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-class RunControlContext(object):
- """
- A context corresponds to an execution thread, process, address space, etc.
- A context can belong to a parent context. Contexts hierarchy can be simple
- plain list or it can form a tree. It is up to target agent developers to choose
- layout that is most descriptive for a given target. Context IDs are valid across
- all services. In other words, all services access same hierarchy of contexts,
- with same IDs, however, each service accesses its own subset of context's
- attributes and functionality, which is relevant to that service.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Run Control Context %s]" % self._props
-
- def getProperties(self):
- """
- Get context properties. See PROP_* definitions for property names.
- Context properties are read only, clients should not try to modify them.
- @return Map of context properties.
- """
- return self._props
-
- def getID(self):
- """
- Retrieve context ID.
- Same as getProperties().get('ID')
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Retrieve parent context ID.
- Same as getProperties().get('ParentID')
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getProcessID(self):
- """
- Retrieve context process ID.
- Same as getProperties().get('ProcessID')
- """
- return self._props.get(PROP_PROCESS_ID)
-
- def getCreatorID(self):
- """
- Retrieve context creator ID.
- Same as getProperties().get('CreatorID')
- """
- return self._props.get(PROP_CREATOR_ID)
-
- def getName(self):
- """
- Retrieve human readable context name.
- Same as getProperties().get('Name')
- """
- return self._props.get(PROP_NAME)
-
- def isContainer(self):
- """
- Utility method to read context property PROP_IS_CONTAINER.
- Executing resume or suspend command on a container causes all its children to resume or suspend.
- @return value of PROP_IS_CONTAINER.
- """
- return self._props.get(PROP_IS_CONTAINER)
-
- def hasState(self):
- """
- Utility method to read context property PROP_HAS_STATE.
- Only context that has a state can be resumed or suspended.
- @return value of PROP_HAS_STATE.
- """
- return self._props.get(PROP_HAS_STATE)
-
- def canSuspend(self):
- """
- Utility method to read context property PROP_CAN_SUSPEND.
- Value 'true' means suspend command is supported by the context,
- however the method does not check that the command can be executed successfully in
- the current state of the context. For example, the command still can fail if context is
- already suspended.
- @return value of PROP_CAN_SUSPEND.
- """
- return self._props.get(PROP_CAN_SUSPEND)
-
- def canResume(self, mode):
- """
- Utility method to read a 'mode' bit in context property PROP_CAN_RESUME.
- Value 'true' means resume command is supported by the context,
- however the method does not check that the command can be executed successfully in
- the current state of the context. For example, the command still can fail if context is
- already resumed.
- @param mode - resume mode, see RM_*.
- @return value of requested bit of PROP_CAN_RESUME.
- """
- b = self._props.get(PROP_CAN_RESUME) or 0
- return (b & (1 << mode)) != 0
-
- def canCount(self, mode):
- """
- Utility method to read a 'mode' bit in context property PROP_CAN_COUNT.
- Value 'true' means resume command with count other then 1 is supported by the context,
- however the method does not check that the command can be executed successfully in
- the current state of the context. For example, the command still can fail if context is
- already resumed.
- @param mode - resume mode, see RM_*.
- @return value of requested bit of PROP_CAN_COUNT.
- """
- b = self._props.get(PROP_CAN_COUNT) or 0
- return (b & (1 << mode)) != 0
-
- def canTerminate(self):
- """
- Utility method to read context property PROP_CAN_TERMINATE.
- Value 'true' means terminate command is supported by the context,
- however the method does not check that the command can be executed successfully in
- the current state of the context. For example, the command still can fail if context is
- already exited.
- @return value of PROP_CAN_SUSPEND.
- """
- return self._props.get(PROP_CAN_TERMINATE)
-
- def getRCGroup(self):
- """
- Utility method to read context property PROP_RC_GROUP -
- context ID of a run control group that contains the context.
- Members of same group are always suspended and resumed together:
- resuming/suspending a context resumes/suspends all members of the group.
- @return value of PROP_RC_GROUP.
- """
- return self._props.get(PROP_RC_GROUP)
-
- def getState(self, done):
- """
- Send a command to retrieve current state of a context.
- @param done - command result call back object.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def suspend(self, done):
- """
- Send a command to suspend a context.
- Also suspends children if context is a container.
- @param done - command result call back object.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
-# def resume(self, mode, count, done):
-# """
-# Send a command to resume a context.
-# Also resumes children if context is a container.
-# @param mode - defines how to resume the context, see RM_*.
-# @param count - if mode implies stepping, defines how many steps to perform.
-# @param done - command result call back object.
-# @return pending command handle, can be used to cancel the command.
-# """
-# raise NotImplementedError("Abstract method")
-
- def resume(self, mode, count, params, done):
- """
- Send a command to resume a context.
- Also resumes children if context is a container.
- @param mode - defines how to resume the context, see RM_*.
- @param count - if mode implies stepping, defines how many steps to perform.
- @param params - resume parameters, for example, step range definition, see RP_*.
- @param done - command result call back object.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def terminate(self, done):
- """
- Send a command to terminate a context.
- @param done - command result call back object.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
-class RunControlListener(object):
- "Service events listener interface."
- def contextAdded(self, contexts):
- """
- Called when new contexts are created.
- @param contexts - array of new context properties.
- """
- pass
- def contextChanged(self, contexts):
- """
- Called when a context properties changed.
- @param contexts - array of new context properties.
- """
- pass
- def contextRemoved(self, context_ids):
- """
- Called when contexts are removed.
- @param context_ids - array of removed context IDs.
- """
- pass
- def contextSuspended(self, context, pc, reason, params):
- """
- Called when a thread is suspended.
- @param context - ID of a context that was suspended.
- @param pc - program counter of the context, can be None.
- @param reason - human readable description of suspend reason.
- @param params - additional, target specific data about suspended context.
- """
- pass
- def contextResumed(self, context):
- """
- Called when a thread is resumed.
- @param context - ID of a context that was resumed.
- """
- pass
- def containerSuspended(self, context, pc, reason, params, suspended_ids):
- """
- Called when target simultaneously suspends multiple threads in a container
- (process, core, etc.).
-
- @param context - ID of a context responsible for the event. It can be container ID or
- any one of container children, for example, it can be thread that hit "suspend all" breakpoint.
- Client expected to move focus (selection) to this context.
- @param pc - program counter of the context.
- @param reason - suspend reason, see REASON_*.
- @param params - additional target specific data about context state, see STATE_*.
- @param suspended_ids - full list of all contexts that were suspended.
- """
- pass
- def containerResumed(self, context_ids):
- """
- Called when target simultaneously resumes multiple threads in a container (process,
- core, etc.).
-
- @param context_ids - full list of all contexts that were resumed.
- """
- pass
- def contextException(self, context, msg):
- """
- Called when an exception is detected in a target thread.
- @param context - ID of a context that caused an exception.
- @param msg - human readable description of the exception.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+from tcf import services
+
+NAME = "RunControl"
+
+# Context property names.
+# Run control context ID */
+PROP_ID = "ID"
+
+# Context parent (owner) ID, for a thread it is same as process ID */
+PROP_PARENT_ID = "ParentID"
+
+# Context process (memory space) ID */
+PROP_PROCESS_ID = "ProcessID"
+
+# ID of a context that created this context */
+PROP_CREATOR_ID = "CreatorID"
+
+# Human readable context name */
+PROP_NAME = "Name"
+
+# true if the context is a container. Container can propagate run control commands to his children */
+PROP_IS_CONTAINER = "IsContainer"
+
+# true if context has execution state - can be suspended/resumed */
+PROP_HAS_STATE = "HasState"
+
+# Bit-set of RM_ values that are supported by the context */
+PROP_CAN_RESUME = "CanResume"
+
+# Bit-set of RM_ values that can be used with count > 1 */
+PROP_CAN_COUNT = "CanCount"
+
+# true if suspend command is supported by the context */
+PROP_CAN_SUSPEND = "CanSuspend"
+
+# true if terminate command is supported by the context */
+PROP_CAN_TERMINATE = "CanTerminate"
+
+# Context ID of a run control group that contains the context.
+# Members of same group are always suspended and resumed together:
+# resuming/suspending a context resumes/suspends all members of the group */
+PROP_RC_GROUP = "RCGroup"
+
+# Context resume modes.
+RM_RESUME = 0
+
+# Step over a single instruction.
+# If the instruction is a function call then don't stop until the function returns.
+
+RM_STEP_OVER = 1
+
+# Step a single instruction.
+# If the instruction is a function call then stop at first instruction of the function.
+RM_STEP_INTO = 2
+
+# Step over a single source code line.
+# If the line contains a function call then don't stop until the function returns.
+RM_STEP_OVER_LINE = 3
+
+# Step a single source code line.
+# If the line contains a function call then stop at first line of the function.
+RM_STEP_INTO_LINE = 4
+
+# Run until control returns from current function.
+RM_STEP_OUT = 5
+
+# Start running backwards.
+# Execution will continue until suspended by command or breakpoint.
+RM_REVERSE_RESUME = 6
+
+# Reverse of RM_STEP_OVER - run backwards over a single instruction.
+# If the instruction is a function call then don't stop until get out of the function.
+RM_REVERSE_STEP_OVER = 7
+
+# Reverse of RM_STEP_INTO.
+# This effectively "un-executes" the previous instruction
+RM_REVERSE_STEP_INTO = 8
+
+# Reverse of RM_STEP_OVER_LINE.
+# Resume backward execution of given context until control reaches an instruction that belongs
+# to a different source line.
+# If the line contains a function call then don't stop until get out of the function.
+# Error is returned if line number information not available.
+RM_REVERSE_STEP_OVER_LINE = 9
+
+# Reverse of RM_STEP_INTO_LINE,
+# Resume backward execution of given context until control reaches an instruction that belongs
+# to a different line of source code.
+# If a function is called, stop at the beginning of the last line of the function code.
+# Error is returned if line number information not available.
+RM_REVERSE_STEP_INTO_LINE = 10
+
+# Reverse of RM_STEP_OUT.
+# Resume backward execution of the given context until control reaches the point where the current function was called.
+RM_REVERSE_STEP_OUT = 11
+
+# Step over instructions until PC is outside the specified range.
+# Any function call within the range is considered to be in range.
+RM_STEP_OVER_RANGE = 12
+
+# Step instruction until PC is outside the specified range for any reason.
+RM_STEP_INTO_RANGE = 13
+
+# Reverse of RM_STEP_OVER_RANGE
+RM_REVERSE_STEP_OVER_RANGE = 14
+
+# Reverse of RM_STEP_INTO_RANGE
+RM_REVERSE_STEP_INTO_RANGE = 15
+
+# Run until the context becomes active - scheduled to run on a target CPU
+RM_UNTIL_ACTIVE = 16
+
+# Run reverse until the context becomes active
+RM_REVERSE_UNTIL_ACTIVE = 17
+
+# State change reason of a context.
+# Reason can be any text, but if it is one of predefined strings,
+# a generic client might be able to handle it better.
+REASON_USER_REQUEST = "Suspended"
+REASON_STEP = "Step"
+REASON_BREAKPOINT = "Breakpoint"
+REASON_EXCEPTION = "Exception"
+REASON_CONTAINER = "Container"
+REASON_WATCHPOINT = "Watchpoint"
+REASON_SIGNAL = "Signal"
+REASON_SHAREDLIB = "Shared Library"
+REASON_ERROR = "Error"
+
+# Optional parameters of context state.
+STATE_SIGNAL = "Signal"
+STATE_SIGNAL_NAME = "SignalName"
+STATE_SIGNAL_DESCRIPTION = "SignalDescription"
+STATE_BREAKPOINT_IDS = "BPs"
+STATE_PC_ERROR = "PCError"
+
+# Optional parameters of resume command.
+# Integer - starting address of step range, inclusive */
+RP_RANGE_START = "RangeStart"
+
+# Integer - ending address of step range, exclusive */
+RP_RANGE_END = "RangeEnd"
+
+class RunControlService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context properties for given context ID.
+
+ @param id - context ID.
+ @param done - callback interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children of given context.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getContext or getChildren commands.
+ @param done - callback interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add run control event listener.
+ @param listener - run control event listener to add.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove run control event listener.
+ @param listener - run control event listener to remove.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class RunControlError(Exception):
+ pass
+
+class DoneGetState(object):
+ def doneGetState(self, token, error, suspended, pc, reason, params):
+ """
+ Called when getState command execution is complete.
+ @param token - pending command handle.
+ @param error - command execution error or None.
+ @param suspended - true if the context is suspended
+ @param pc - program counter of the context (if suspended).
+ @param reason - suspend reason (if suspended), see REASON_*.
+ @param params - additional target specific data about context state, see STATE_*.
+ """
+ pass
+
+class DoneCommand(object):
+ def doneCommand(self, token, error):
+ """
+ Called when run control command execution is complete.
+ @param token - pending command handle.
+ @param error - command execution error or None.
+ """
+ pass
+
+class DoneGetContext(object):
+ "Client callback interface for getContext()."
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ "Client callback interface for getChildren()."
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class RunControlContext(object):
+ """
+ A context corresponds to an execution thread, process, address space, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Run Control Context %s]" % self._props
+
+ def getProperties(self):
+ """
+ Get context properties. See PROP_* definitions for property names.
+ Context properties are read only, clients should not try to modify them.
+ @return Map of context properties.
+ """
+ return self._props
+
+ def getID(self):
+ """
+ Retrieve context ID.
+ Same as getProperties().get('ID')
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Retrieve parent context ID.
+ Same as getProperties().get('ParentID')
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getProcessID(self):
+ """
+ Retrieve context process ID.
+ Same as getProperties().get('ProcessID')
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def getCreatorID(self):
+ """
+ Retrieve context creator ID.
+ Same as getProperties().get('CreatorID')
+ """
+ return self._props.get(PROP_CREATOR_ID)
+
+ def getName(self):
+ """
+ Retrieve human readable context name.
+ Same as getProperties().get('Name')
+ """
+ return self._props.get(PROP_NAME)
+
+ def isContainer(self):
+ """
+ Utility method to read context property PROP_IS_CONTAINER.
+ Executing resume or suspend command on a container causes all its children to resume or suspend.
+ @return value of PROP_IS_CONTAINER.
+ """
+ return self._props.get(PROP_IS_CONTAINER)
+
+ def hasState(self):
+ """
+ Utility method to read context property PROP_HAS_STATE.
+ Only context that has a state can be resumed or suspended.
+ @return value of PROP_HAS_STATE.
+ """
+ return self._props.get(PROP_HAS_STATE)
+
+ def canSuspend(self):
+ """
+ Utility method to read context property PROP_CAN_SUSPEND.
+ Value 'true' means suspend command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already suspended.
+ @return value of PROP_CAN_SUSPEND.
+ """
+ return self._props.get(PROP_CAN_SUSPEND)
+
+ def canResume(self, mode):
+ """
+ Utility method to read a 'mode' bit in context property PROP_CAN_RESUME.
+ Value 'true' means resume command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already resumed.
+ @param mode - resume mode, see RM_*.
+ @return value of requested bit of PROP_CAN_RESUME.
+ """
+ b = self._props.get(PROP_CAN_RESUME) or 0
+ return (b & (1 << mode)) != 0
+
+ def canCount(self, mode):
+ """
+ Utility method to read a 'mode' bit in context property PROP_CAN_COUNT.
+ Value 'true' means resume command with count other then 1 is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already resumed.
+ @param mode - resume mode, see RM_*.
+ @return value of requested bit of PROP_CAN_COUNT.
+ """
+ b = self._props.get(PROP_CAN_COUNT) or 0
+ return (b & (1 << mode)) != 0
+
+ def canTerminate(self):
+ """
+ Utility method to read context property PROP_CAN_TERMINATE.
+ Value 'true' means terminate command is supported by the context,
+ however the method does not check that the command can be executed successfully in
+ the current state of the context. For example, the command still can fail if context is
+ already exited.
+ @return value of PROP_CAN_SUSPEND.
+ """
+ return self._props.get(PROP_CAN_TERMINATE)
+
+ def getRCGroup(self):
+ """
+ Utility method to read context property PROP_RC_GROUP -
+ context ID of a run control group that contains the context.
+ Members of same group are always suspended and resumed together:
+ resuming/suspending a context resumes/suspends all members of the group.
+ @return value of PROP_RC_GROUP.
+ """
+ return self._props.get(PROP_RC_GROUP)
+
+ def getState(self, done):
+ """
+ Send a command to retrieve current state of a context.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def suspend(self, done):
+ """
+ Send a command to suspend a context.
+ Also suspends children if context is a container.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+# def resume(self, mode, count, done):
+# """
+# Send a command to resume a context.
+# Also resumes children if context is a container.
+# @param mode - defines how to resume the context, see RM_*.
+# @param count - if mode implies stepping, defines how many steps to perform.
+# @param done - command result call back object.
+# @return pending command handle, can be used to cancel the command.
+# """
+# raise NotImplementedError("Abstract method")
+
+ def resume(self, mode, count, params, done):
+ """
+ Send a command to resume a context.
+ Also resumes children if context is a container.
+ @param mode - defines how to resume the context, see RM_*.
+ @param count - if mode implies stepping, defines how many steps to perform.
+ @param params - resume parameters, for example, step range definition, see RP_*.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def terminate(self, done):
+ """
+ Send a command to terminate a context.
+ @param done - command result call back object.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+class RunControlListener(object):
+ "Service events listener interface."
+ def contextAdded(self, contexts):
+ """
+ Called when new contexts are created.
+ @param contexts - array of new context properties.
+ """
+ pass
+ def contextChanged(self, contexts):
+ """
+ Called when a context properties changed.
+ @param contexts - array of new context properties.
+ """
+ pass
+ def contextRemoved(self, context_ids):
+ """
+ Called when contexts are removed.
+ @param context_ids - array of removed context IDs.
+ """
+ pass
+ def contextSuspended(self, context, pc, reason, params):
+ """
+ Called when a thread is suspended.
+ @param context - ID of a context that was suspended.
+ @param pc - program counter of the context, can be None.
+ @param reason - human readable description of suspend reason.
+ @param params - additional, target specific data about suspended context.
+ """
+ pass
+ def contextResumed(self, context):
+ """
+ Called when a thread is resumed.
+ @param context - ID of a context that was resumed.
+ """
+ pass
+ def containerSuspended(self, context, pc, reason, params, suspended_ids):
+ """
+ Called when target simultaneously suspends multiple threads in a container
+ (process, core, etc.).
+
+ @param context - ID of a context responsible for the event. It can be container ID or
+ any one of container children, for example, it can be thread that hit "suspend all" breakpoint.
+ Client expected to move focus (selection) to this context.
+ @param pc - program counter of the context.
+ @param reason - suspend reason, see REASON_*.
+ @param params - additional target specific data about context state, see STATE_*.
+ @param suspended_ids - full list of all contexts that were suspended.
+ """
+ pass
+ def containerResumed(self, context_ids):
+ """
+ Called when target simultaneously resumes multiple threads in a container (process,
+ core, etc.).
+
+ @param context_ids - full list of all contexts that were resumed.
+ """
+ pass
+ def contextException(self, context, msg):
+ """
+ Called when an exception is detected in a target thread.
+ @param context - ID of a context that caused an exception.
+ @param msg - human readable description of the exception.
+ """
+ pass
diff --git a/python/src/tcf/services/stacktrace.py b/python/src/tcf/services/stacktrace.py
index 0240ec1db..dfbc4c665 100644
--- a/python/src/tcf/services/stacktrace.py
+++ b/python/src/tcf/services/stacktrace.py
@@ -1,162 +1,162 @@
-#******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-#******************************************************************************
-
-from tcf import services
-
-NAME = "StackTrace"
-
-#
-# Stack frame context property names.
-#
-PROP_ID = "ID" # String, stack frame ID
-PROP_PARENT_ID = "ParentID" # String, stack frame parent ID
-PROP_PROCESS_ID = "ProcessID" # String, stack frame process ID
-PROP_NAME = "Name" # String, human readable name
-PROP_TOP_FRAME = "TopFrame" # Boolean, true if the frame is top frame on a stack
-PROP_LEVEL = "Level" # Integer, stack frame level, starting from stack bottom
-PROP_FRAME_ADDRESS = "FP" # Number, stack frame memory address
-PROP_RETURN_ADDRESS = "RP" # Number, return address
-PROP_INSTRUCTION_ADDRESS = "IP" # Number, instruction pointer
-PROP_ARGUMENTS_COUNT = "ArgsCnt" # Integer, number of function arguments
-PROP_ARGUMENTS_ADDRESS = "ArgsAddr" # Number, memory address of function arguments
-
-class StackTraceService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, ids, done):
- """
- Retrieve context info for given context IDs.
-
- The command will fail if parent thread is not suspended.
- Client can use Run Control service to suspend a thread.
-
- @param ids - array of context IDs.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve stack trace context list.
- Parent context usually corresponds to an execution thread.
- Some targets have more then one stack. In such case children of a thread
- are stacks, and stack frames are deeper in the hierarchy - they can be
- retrieved with additional getChildren commands.
-
- The command will fail if parent thread is not suspended.
- Client can use Run Control service to suspend a thread.
-
- @param parent_context_id - parent context ID.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, contexts):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param contexts - array of context data or None if error.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- Stack frames are ordered from stack bottom to top.
- """
- pass
-
-class StackTraceContext(object):
- """
- StackTraceContext represents stack trace objects - stacks and stack frames.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Stack Trace Context %s]" % self._props
-
- def getID(self):
- """
- Get Context ID.
- @return context ID.
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Get parent context ID.
- @return parent context ID.
- """
- return self._props.get(PROP_PARENT_ID)
-
- def getName(self):
- """
- Get context name - if context represents a stack.
- @return context name or None.
- """
- return self._props.get(PROP_NAME)
-
- def getFrameAddress(self):
- """
- Get memory address of this frame.
- @return address or None if not a stack frame.
- """
- return self._props.get(PROP_FRAME_ADDRESS)
-
- def getReturnAddress(self):
- """
- Get program counter saved in this stack frame -
- it is address of instruction to be executed when the function returns.
- @return return address or None if not a stack frame.
- """
- return self._props.get(PROP_RETURN_ADDRESS)
-
- def getInstructionAddress(self):
- """
- Get address of the next instruction to be executed in this stack frame.
- For top frame it is same as PC register value.
- For other frames it is same as return address of the next frame.
- @return instruction address or None if not a stack frame.
- """
- return self._props.get(PROP_INSTRUCTION_ADDRESS)
-
- def getArgumentsCount(self):
- """
- Get number of function arguments for this frame.
- @return function arguments count.
- """
- return self._props.get(PROP_ARGUMENTS_COUNT)
-
- def getArgumentsAddress(self):
- """
- Get address of function arguments area in memory.
- @return function arguments address or None if not available.
- """
- return self._props.get(PROP_ARGUMENTS_ADDRESS, 0)
-
- def getProperties(self):
- """
- Get complete map of context properties.
- @return map of context properties.
- """
- return self._props
+#******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+#******************************************************************************
+
+from tcf import services
+
+NAME = "StackTrace"
+
+#
+# Stack frame context property names.
+#
+PROP_ID = "ID" # String, stack frame ID
+PROP_PARENT_ID = "ParentID" # String, stack frame parent ID
+PROP_PROCESS_ID = "ProcessID" # String, stack frame process ID
+PROP_NAME = "Name" # String, human readable name
+PROP_TOP_FRAME = "TopFrame" # Boolean, true if the frame is top frame on a stack
+PROP_LEVEL = "Level" # Integer, stack frame level, starting from stack bottom
+PROP_FRAME_ADDRESS = "FP" # Number, stack frame memory address
+PROP_RETURN_ADDRESS = "RP" # Number, return address
+PROP_INSTRUCTION_ADDRESS = "IP" # Number, instruction pointer
+PROP_ARGUMENTS_COUNT = "ArgsCnt" # Integer, number of function arguments
+PROP_ARGUMENTS_ADDRESS = "ArgsAddr" # Number, memory address of function arguments
+
+class StackTraceService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, ids, done):
+ """
+ Retrieve context info for given context IDs.
+
+ The command will fail if parent thread is not suspended.
+ Client can use Run Control service to suspend a thread.
+
+ @param ids - array of context IDs.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve stack trace context list.
+ Parent context usually corresponds to an execution thread.
+ Some targets have more then one stack. In such case children of a thread
+ are stacks, and stack frames are deeper in the hierarchy - they can be
+ retrieved with additional getChildren commands.
+
+ The command will fail if parent thread is not suspended.
+ Client can use Run Control service to suspend a thread.
+
+ @param parent_context_id - parent context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, contexts):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param contexts - array of context data or None if error.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ Stack frames are ordered from stack bottom to top.
+ """
+ pass
+
+class StackTraceContext(object):
+ """
+ StackTraceContext represents stack trace objects - stacks and stack frames.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Stack Trace Context %s]" % self._props
+
+ def getID(self):
+ """
+ Get Context ID.
+ @return context ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ @return parent context ID.
+ """
+ return self._props.get(PROP_PARENT_ID)
+
+ def getName(self):
+ """
+ Get context name - if context represents a stack.
+ @return context name or None.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getFrameAddress(self):
+ """
+ Get memory address of this frame.
+ @return address or None if not a stack frame.
+ """
+ return self._props.get(PROP_FRAME_ADDRESS)
+
+ def getReturnAddress(self):
+ """
+ Get program counter saved in this stack frame -
+ it is address of instruction to be executed when the function returns.
+ @return return address or None if not a stack frame.
+ """
+ return self._props.get(PROP_RETURN_ADDRESS)
+
+ def getInstructionAddress(self):
+ """
+ Get address of the next instruction to be executed in this stack frame.
+ For top frame it is same as PC register value.
+ For other frames it is same as return address of the next frame.
+ @return instruction address or None if not a stack frame.
+ """
+ return self._props.get(PROP_INSTRUCTION_ADDRESS)
+
+ def getArgumentsCount(self):
+ """
+ Get number of function arguments for this frame.
+ @return function arguments count.
+ """
+ return self._props.get(PROP_ARGUMENTS_COUNT)
+
+ def getArgumentsAddress(self):
+ """
+ Get address of function arguments area in memory.
+ @return function arguments address or None if not available.
+ """
+ return self._props.get(PROP_ARGUMENTS_ADDRESS, 0)
+
+ def getProperties(self):
+ """
+ Get complete map of context properties.
+ @return map of context properties.
+ """
+ return self._props
diff --git a/python/src/tcf/services/streams.py b/python/src/tcf/services/streams.py
index 283c77e30..446941b23 100644
--- a/python/src/tcf/services/streams.py
+++ b/python/src/tcf/services/streams.py
@@ -1,224 +1,224 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Streams service is a generic interface to support streaming of data between host and remote agents.
-
-The service supports:
- 1. Asynchronous overlapped data streaming: multiple 'read' or 'write' command can be issued at same time, both peers
- can continue data processing concurrently with data transmission.
- 2. Multicast: multiple clients can receive data from same stream.
- 3. Subscription model: clients are required to expressed interest in particular streams by subscribing for the service.
- 4. Flow control: peers can throttle data flow of individual streams by delaying 'read' and 'write' commands.
-"""
-
-from tcf import services
-
-NAME = "Streams"
-
-class StreamsService(services.Service):
- def getName(self):
- return NAME
-
- def subscribe(self, stream_type, listener, done):
- """
- Clients must subscribe for one or more stream types to be able to send or receive stream data.
- Subscribers receive notifications when a stream of given type is created or disposed.
- Subscribers are required to respond with 'read' or 'disconnect' commands as necessary.
- @param stream_type - the stream source type.
- @param listener - client implementation of StreamsListener interface.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def unsubscribe(self, stream_type, listener, done):
- """
- Unsubscribe the client from given stream source type.
- @param stream_type - the stream source type.
- @param listener - client implementation of StreamsListener interface.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def read(self, stream_id, size, done):
- """
- Read data from a stream. If stream buffer is empty, the command will wait until data is available.
- Remote peer will continue to process other commands while 'read' command is pending.
- Client can send more 'read' commands without waiting for the first command to complete.
- Doing that improves communication channel bandwidth utilization.
- Pending 'read' commands will be executed in same order as issued.
- Client can delay sending of 'read' command if it is not ready to receive more data,
- however, delaying for too long can cause stream buffer overflow and lost of data.
- @param stream_id - ID of the stream.
- @param size - max number of bytes to read.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def write(self, stream_id, buf, offset, size, done):
- """
- Write data to a stream. If stream buffer is full, the command will wait until space is available.
- Remote peer will continue to process other commands while 'write' command is pending.
- Client can send more 'write' commands without waiting for the first command to complete.
- Doing that improves communication channel bandwidth utilization.
- Pending 'write' commands will be executed in same order as issued.
- @param stream_id - ID of the stream.
- @param buf - buffer that contains stream data.
- @param offset - byte offset in the buffer.
- @param size - number of bytes to write.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def eos(self, stream_id, done):
- """
- Send End Of Stream marker to a stream. No more writing to the stream is allowed after that.
- @param stream_id - ID of the stream.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def connect(self, stream_id, done):
- """
- Connect client to a stream.
- Some data might be dropped from the stream by the time "connect" command is executed.
- Client should be able to re-sync with stream data if it wants to read from such stream.
- If a client wants to read a stream from the beginning it should use "subscribe" command
- instead of "connect".
- @param stream_id - ID of the stream.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def disconnect(self, stream_id, done):
- """
- Disconnect client from a stream.
- @param stream_id - ID of the stream.
- @param done - command result call back object.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
-
-class StreamsListener(object):
- """
- Clients can implement StreamsListener interface to be notified
- when a stream is created or disposed. The interface is registered with 'subscribe' command.
-
- When new stream is created, client must decide if it is interested in that particular stream instance.
- If not interested, client should send 'disconnect' command to allow remote peer to free resources and bandwidth.
- If not disconnected, client is required to send 'read' commands as necessary to prevent stream buffer overflow.
- """
-
- def created(self, stream_type, stream_id, context_id):
- """
- Called when a new stream is created.
- @param stream_type - source type of the stream.
- @param stream_id - ID of the stream.
- @param context_id - a context ID that is associated with the stream, or None.
- Exact meaning of the context ID depends on stream type.
- Stream types and context IDs are defined by services that use Streams service to transmit data.
- """
- pass
-
- def disposed(self, stream_type, stream_id):
- """
- Called when a stream is disposed.
- @param stream_type - source type of the stream.
- @param stream_id - ID of the stream.
- """
- pass
-
-class DoneSubscribe(object):
- """
- Call back interface for 'subscribe' command.
- """
- def doneSubscribe(self, token, error):
- pass
-
-class DoneUnsubscribe(object):
- """
- Call back interface for 'unsubscribe' command.
- """
- def doneUnsubscribe(self, token, error):
- pass
-
-class DoneRead(object):
- """
- Call back interface for 'read' command.
- """
- def doneRead(self, token, error, lost_size, data, eos):
- """
- Called when 'read' command is done.
- @param token - command handle.
- @param error - error object or None.
- @param lost_size - number of bytes that were lost because of buffer overflow.
- 'lost_size' -1 means unknown number of bytes were lost.
- if both 'lost_size' and 'data.length' are non-zero then lost bytes are considered
- located right before read bytes.
- @param data - bytes read from the stream.
- @param eos - true if end of stream was reached.
- """
- pass
-
-class DoneWrite(object):
- """
- Call back interface for 'write' command.
- """
- def doneWrite(self, token, error):
- """
- Called when 'write' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneEOS(object):
- """
- Call back interface for 'eos' command.
- """
- def doneEOS(self, token, error):
- """
- Called when 'eos' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneConnect(object):
- """
- Call back interface for 'connect' command.
- """
- def doneConnect(self, token, error):
- """
- Called when 'connect' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
-
-class DoneDisconnect(object):
- """
- Call back interface for 'disconnect' command.
- """
- def doneDisconnect(self, token, error):
- """
- Called when 'disconnect' command is done.
- @param token - command handle.
- @param error - error object or None.
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Streams service is a generic interface to support streaming of data between host and remote agents.
+
+The service supports:
+ 1. Asynchronous overlapped data streaming: multiple 'read' or 'write' command can be issued at same time, both peers
+ can continue data processing concurrently with data transmission.
+ 2. Multicast: multiple clients can receive data from same stream.
+ 3. Subscription model: clients are required to expressed interest in particular streams by subscribing for the service.
+ 4. Flow control: peers can throttle data flow of individual streams by delaying 'read' and 'write' commands.
+"""
+
+from tcf import services
+
+NAME = "Streams"
+
+class StreamsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def subscribe(self, stream_type, listener, done):
+ """
+ Clients must subscribe for one or more stream types to be able to send or receive stream data.
+ Subscribers receive notifications when a stream of given type is created or disposed.
+ Subscribers are required to respond with 'read' or 'disconnect' commands as necessary.
+ @param stream_type - the stream source type.
+ @param listener - client implementation of StreamsListener interface.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def unsubscribe(self, stream_type, listener, done):
+ """
+ Unsubscribe the client from given stream source type.
+ @param stream_type - the stream source type.
+ @param listener - client implementation of StreamsListener interface.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def read(self, stream_id, size, done):
+ """
+ Read data from a stream. If stream buffer is empty, the command will wait until data is available.
+ Remote peer will continue to process other commands while 'read' command is pending.
+ Client can send more 'read' commands without waiting for the first command to complete.
+ Doing that improves communication channel bandwidth utilization.
+ Pending 'read' commands will be executed in same order as issued.
+ Client can delay sending of 'read' command if it is not ready to receive more data,
+ however, delaying for too long can cause stream buffer overflow and lost of data.
+ @param stream_id - ID of the stream.
+ @param size - max number of bytes to read.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def write(self, stream_id, buf, offset, size, done):
+ """
+ Write data to a stream. If stream buffer is full, the command will wait until space is available.
+ Remote peer will continue to process other commands while 'write' command is pending.
+ Client can send more 'write' commands without waiting for the first command to complete.
+ Doing that improves communication channel bandwidth utilization.
+ Pending 'write' commands will be executed in same order as issued.
+ @param stream_id - ID of the stream.
+ @param buf - buffer that contains stream data.
+ @param offset - byte offset in the buffer.
+ @param size - number of bytes to write.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def eos(self, stream_id, done):
+ """
+ Send End Of Stream marker to a stream. No more writing to the stream is allowed after that.
+ @param stream_id - ID of the stream.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def connect(self, stream_id, done):
+ """
+ Connect client to a stream.
+ Some data might be dropped from the stream by the time "connect" command is executed.
+ Client should be able to re-sync with stream data if it wants to read from such stream.
+ If a client wants to read a stream from the beginning it should use "subscribe" command
+ instead of "connect".
+ @param stream_id - ID of the stream.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def disconnect(self, stream_id, done):
+ """
+ Disconnect client from a stream.
+ @param stream_id - ID of the stream.
+ @param done - command result call back object.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class StreamsListener(object):
+ """
+ Clients can implement StreamsListener interface to be notified
+ when a stream is created or disposed. The interface is registered with 'subscribe' command.
+
+ When new stream is created, client must decide if it is interested in that particular stream instance.
+ If not interested, client should send 'disconnect' command to allow remote peer to free resources and bandwidth.
+ If not disconnected, client is required to send 'read' commands as necessary to prevent stream buffer overflow.
+ """
+
+ def created(self, stream_type, stream_id, context_id):
+ """
+ Called when a new stream is created.
+ @param stream_type - source type of the stream.
+ @param stream_id - ID of the stream.
+ @param context_id - a context ID that is associated with the stream, or None.
+ Exact meaning of the context ID depends on stream type.
+ Stream types and context IDs are defined by services that use Streams service to transmit data.
+ """
+ pass
+
+ def disposed(self, stream_type, stream_id):
+ """
+ Called when a stream is disposed.
+ @param stream_type - source type of the stream.
+ @param stream_id - ID of the stream.
+ """
+ pass
+
+class DoneSubscribe(object):
+ """
+ Call back interface for 'subscribe' command.
+ """
+ def doneSubscribe(self, token, error):
+ pass
+
+class DoneUnsubscribe(object):
+ """
+ Call back interface for 'unsubscribe' command.
+ """
+ def doneUnsubscribe(self, token, error):
+ pass
+
+class DoneRead(object):
+ """
+ Call back interface for 'read' command.
+ """
+ def doneRead(self, token, error, lost_size, data, eos):
+ """
+ Called when 'read' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ @param lost_size - number of bytes that were lost because of buffer overflow.
+ 'lost_size' -1 means unknown number of bytes were lost.
+ if both 'lost_size' and 'data.length' are non-zero then lost bytes are considered
+ located right before read bytes.
+ @param data - bytes read from the stream.
+ @param eos - true if end of stream was reached.
+ """
+ pass
+
+class DoneWrite(object):
+ """
+ Call back interface for 'write' command.
+ """
+ def doneWrite(self, token, error):
+ """
+ Called when 'write' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneEOS(object):
+ """
+ Call back interface for 'eos' command.
+ """
+ def doneEOS(self, token, error):
+ """
+ Called when 'eos' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneConnect(object):
+ """
+ Call back interface for 'connect' command.
+ """
+ def doneConnect(self, token, error):
+ """
+ Called when 'connect' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
+
+class DoneDisconnect(object):
+ """
+ Call back interface for 'disconnect' command.
+ """
+ def doneDisconnect(self, token, error):
+ """
+ Called when 'disconnect' command is done.
+ @param token - command handle.
+ @param error - error object or None.
+ """
+ pass
diff --git a/python/src/tcf/services/symbols.py b/python/src/tcf/services/symbols.py
index 9e3e8df75..bde195f78 100644
--- a/python/src/tcf/services/symbols.py
+++ b/python/src/tcf/services/symbols.py
@@ -1,391 +1,392 @@
-#******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-#******************************************************************************
-
-from tcf import services
-
-# Service name.
-NAME = "Symbols"
-
-class SymbolClass:
- unknown = 0 # unknown symbol class
- value = 1 # constant value
- reference = 2 # variable data object
- function = 3 # function body
- type = 4 # a type
-
-class TypeClass:
- unknown = 0 # unknown type class
- cardinal = 1 # unsigned integer
- integer = 2 # signed integer
- real = 3 # float, double
- pointer = 4 # pointer to anything.
- array = 5 # array of anything.
- composite = 6 # struct, union, or class.
- enumeration = 7 # enumeration type.
- function = 8 # function type.
-
-#
-# Symbol context property names.
-#
-PROP_ID = "ID"
-PROP_OWNER_ID = "OwnerID"
-PROP_UPDATE_POLICY = "UpdatePolicy"
-PROP_NAME = "Name"
-PROP_SYMBOL_CLASS = "Class"
-PROP_TYPE_CLASS = "TypeClass"
-PROP_TYPE_ID = "TypeID"
-PROP_BASE_TYPE_ID = "BaseTypeID"
-PROP_INDEX_TYPE_ID = "IndexTypeID"
-PROP_SIZE = "Size"
-PROP_LENGTH = "Length"
-PROP_LOWER_BOUND = "LowerBound"
-PROP_UPPER_BOUND = "UpperBound"
-PROP_OFFSET = "Offset"
-PROP_ADDRESS = "Address"
-PROP_VALUE = "Value"
-PROP_BIG_ENDIAN = "BigEndian"
-PROP_REGISTER = "Register"
-
-#
-# Symbol context properties update policies.
-#
-
-# Update policy "Memory Map": symbol properties become invalid when
-# memory map changes - when modules are loaded or unloaded.
-# Symbol OwnerID indicates memory space (process) that is invalidation events source.
-# Most static variables and types have this update policy.
-UPDATE_ON_MEMORY_MAP_CHANGES = 0
-
-# Update policy "Execution State": symbol properties become invalid when
-# execution state changes - a thread is suspended, resumed or exited.
-# Symbol OwnerID indicates executable context (thread) that is invalidation events source.
-# Most stack (auto) variables have this update policy.
-UPDATE_ON_EXE_STATE_CHANGES = 1
-
-
-class Symbol(object):
- """
- Symbol context interface.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Symbol Context %s]" % self._props
-
- def getID(self):
- """
- Get symbol ID.
- @return symbol ID.
- """
- return self._props.get(PROP_ID)
-
- def getOwnerID(self):
- """
- Get symbol owner ID.
- The owner can a thread or memory space (process).
- Certain changes in owner state can invalidate cached symbol properties,
- see getUpdatePolicy() and UPDATE_*.
- """
- return self._props.get(PROP_OWNER_ID)
-
- def getUpdatePolicy(self):
- """
- Get symbol properties update policy ID.
- Symbol properties can change during program execution.
- If a client wants to cache symbols, it should invalidate cached data
- according to update policies of cached symbols.
- @return symbol update policy ID, see UPDATE_*
- """
- return self._props.get(PROP_UPDATE_POLICY)
-
- def getName(self):
- """
- Get symbol name.
- @return symbol name or None.
- """
- return self._props.get(PROP_NAME)
-
- def getSymbolClass(self):
- """
- Get symbol class.
- @return symbol class.
- """
- return self._props.get(PROP_SYMBOL_CLASS)
-
- def getTypeClass(self):
- """
- Get symbol type class.
- @return type class.
- """
- return self._props.get(PROP_TYPE_CLASS)
-
- def getTypeID(self):
- """
- Get type ID.
- If the symbol is a type and not a 'typedef', return same as getID().
- @return type ID.
- """
- return self._props.get(PROP_TYPE_ID)
-
- def getBaseTypeID(self):
- """
- Get base type ID.
- If this symbol is a
- pointer type - return pointed type
- array type - return element type
- function type - return function result type
- class type - return base class
- otherwise return None.
- @return type ID.
- """
- return self._props.get(PROP_BASE_TYPE_ID)
-
- def getIndexTypeID(self):
- """
- Get index type ID.
- If this symbol is a
- array type - return array index type
- otherwise return None.
- @return type ID.
- """
- return self._props.get(PROP_INDEX_TYPE_ID)
-
- def getSize(self):
- """
- Return value size of the symbol (or type).
- @return size in bytes.
- """
- return self._props.get(PROP_SIZE, 0)
-
- def getLength(self):
- """
- If symbol is an array type - return number of elements.
- @return number of elements.
- """
- return self._props.get(PROP_LENGTH, 0)
-
- def getLowerBound(self):
- """
- If symbol is an array type - return array index lower bound.
- @return lower bound.
- """
- return self._props.get(PROP_LOWER_BOUND)
-
- def getUpperBound(self):
- """
- If symbol is an array type - return array index upper bound.
- @return upper bound.
- """
- return self._props.get(PROP_UPPER_BOUND)
-
- def getOffset(self):
- """
- Return offset from 'this' for member of class, struct or union.
- @return offset in bytes.
- """
- return self._props.get(PROP_OFFSET, 0)
-
- def getAddress(self):
- """
- Return address of the symbol.
- @return address or None.
- """
- return self._props.get(PROP_ADDRESS)
-
- def getValue(self):
- """
- If symbol is a constant object, return its value.
- @return symbol value as array of bytes.
- """
- return self._props.get(PROP_VALUE)
-
- def isBigEndian(self):
- """
- Get symbol values endianness.
- @return true if symbol is big-endian.
- """
- return self._props.get(PROP_BIG_ENDIAN, False)
-
- def getRegisterID(self):
- """
- Return register ID if the symbol represents a register variable.
- @return register ID or None.
- """
- return self._props.get(PROP_REGISTER)
-
- def getProperties(self):
- """
- Get complete map of context properties.
- @return map of context properties.
- """
- return self._props
-
-class SymbolsService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve symbol context info for given symbol ID.
- @see Symbol
-
- @param id - symbol context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve children IDs for given parent ID.
- Meaning of the operation depends on parent kind:
- 1. struct, union, or class type - get fields
- 2. enumeration type - get enumerators
-
- @param parent_context_id - parent symbol context ID.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def find(self, context_id, ip, name, done):
- """
- Search symbol with given name in given context.
- The context can be memory space, process, thread or stack frame.
-
- @param context_id - a search scope.
- @param ip - instruction pointer - ignored if context_id is a stack frame ID
- @param name - symbol name.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def findByAddr(self, context_id, addr, done):
- """
- Search symbol with given address in given context.
- The context can be memory space, process, thread or stack frame.
-
- @param context_id - a search scope.
- @param addr - symbol address.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def list(self, context_id, done):
- """
- List all symbols in given context.
- The context can be a stack frame.
-
- @param context_id - a scope.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
- def findFrameInfo(self, context_id, address, done):
- """
- Retrieve stack tracing commands for given instruction address in a context memory.
- @param context_id - exacutable context ID.
- @param address - instruction address.
- @param done - call back interface called when operation is completed.
- @return - pending command handle.
- """
- raise NotImplementedError("Abstract method")
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context - context properties.
- """
- pass
-class DoneGetChildren(object):
- """
- Client call back interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param token - command handle
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-class DoneFind(object):
- """
- Client call back interface for find().
- """
- def doneFind(self, token, error, symbol_id):
- """
- Called when symbol search is done.
- @param token - command handle.
- @param error - error description if operation failed, None if succeeded.
- @param symbol_id - symbol ID.
- """
- pass
-
-class DoneList(object):
- """
- Client call back interface for list().
- """
- def doneList(self, token, error, symbol_ids):
- """
- Called when symbol list retrieval is done.
- @param token - command handle.
- @param error - error description if operation failed, None if succeeded.
- @param symbol_ids - array of symbol IDs.
- """
-
-
-#
-# Command codes that are used to calculate frame pointer and register values during stack tracing.
-#
-
-# Load a number to the evaluation stack. Command argument is the number.
-CMD_NUMBER = 1
-
-# Load a register value to the evaluation stack. Command argument is the register ID.
-CMD_REGISTER = 2
-
-# Load frame address to the evaluation stack.
-CMD_FP = 3
-
-# Read memory at address on the top of the evaluation stack. Command arguments are
-# the value size (Number) and endianness (Boolean, false - little-endian, true - big-endian).
-CMD_DEREF = 4
-
-# Add two values on top of the evaluation stack
-CMD_ADD = 5
-
-class DoneFindFrameInfo(object):
- """
- Client call back interface for findFrameInfo().
- """
- def doneFindFrameInfo(self, token, error, address, size, fp_cmds, reg_cmds):
- """
- Called when stack tracing information retrieval is done.
- @param token - command handle.
- @param error - error description if operation failed, None if succeeded.
- @param address - start of instruction address range
- @param size - size of instruction address range
- @param fp_cmds - commands to calculate stack frame pointer
- @param reg_cmds - map register IDs -> commands to calculate register values
- """
- pass
+#******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+#******************************************************************************
+
+from tcf import services
+
+# Service name.
+NAME = "Symbols"
+
+class SymbolClass:
+ unknown = 0 # unknown symbol class
+ value = 1 # constant value
+ reference = 2 # variable data object
+ function = 3 # function body
+ type = 4 # a type
+
+class TypeClass:
+ unknown = 0 # unknown type class
+ cardinal = 1 # unsigned integer
+ integer = 2 # signed integer
+ real = 3 # float, double
+ pointer = 4 # pointer to anything.
+ array = 5 # array of anything.
+ composite = 6 # struct, union, or class.
+ enumeration = 7 # enumeration type.
+ function = 8 # function type.
+
+#
+# Symbol context property names.
+#
+PROP_ID = "ID"
+PROP_OWNER_ID = "OwnerID"
+PROP_UPDATE_POLICY = "UpdatePolicy"
+PROP_NAME = "Name"
+PROP_SYMBOL_CLASS = "Class"
+PROP_TYPE_CLASS = "TypeClass"
+PROP_TYPE_ID = "TypeID"
+PROP_BASE_TYPE_ID = "BaseTypeID"
+PROP_INDEX_TYPE_ID = "IndexTypeID"
+PROP_SIZE = "Size"
+PROP_LENGTH = "Length"
+PROP_LOWER_BOUND = "LowerBound"
+PROP_UPPER_BOUND = "UpperBound"
+PROP_OFFSET = "Offset"
+PROP_ADDRESS = "Address"
+PROP_VALUE = "Value"
+PROP_BIG_ENDIAN = "BigEndian"
+PROP_REGISTER = "Register"
+
+#
+# Symbol context properties update policies.
+#
+
+# Update policy "Memory Map": symbol properties become invalid when
+# memory map changes - when modules are loaded or unloaded.
+# Symbol OwnerID indicates memory space (process) that is invalidation events source.
+# Most static variables and types have this update policy.
+UPDATE_ON_MEMORY_MAP_CHANGES = 0
+
+# Update policy "Execution State": symbol properties become invalid when
+# execution state changes - a thread is suspended, resumed or exited.
+# Symbol OwnerID indicates executable context (thread) that is invalidation events source.
+# Most stack (auto) variables have this update policy.
+UPDATE_ON_EXE_STATE_CHANGES = 1
+
+
+class Symbol(object):
+ """
+ Symbol context interface.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Symbol Context %s]" % self._props
+
+ def getID(self):
+ """
+ Get symbol ID.
+ @return symbol ID.
+ """
+ return self._props.get(PROP_ID)
+
+ def getOwnerID(self):
+ """
+ Get symbol owner ID.
+ The owner can a thread or memory space (process).
+ Certain changes in owner state can invalidate cached symbol properties,
+ see getUpdatePolicy() and UPDATE_*.
+ """
+ return self._props.get(PROP_OWNER_ID)
+
+ def getUpdatePolicy(self):
+ """
+ Get symbol properties update policy ID.
+ Symbol properties can change during program execution.
+ If a client wants to cache symbols, it should invalidate cached data
+ according to update policies of cached symbols.
+ @return symbol update policy ID, see UPDATE_*
+ """
+ return self._props.get(PROP_UPDATE_POLICY)
+
+ def getName(self):
+ """
+ Get symbol name.
+ @return symbol name or None.
+ """
+ return self._props.get(PROP_NAME)
+
+ def getSymbolClass(self):
+ """
+ Get symbol class.
+ @return symbol class.
+ """
+ return self._props.get(PROP_SYMBOL_CLASS)
+
+ def getTypeClass(self):
+ """
+ Get symbol type class.
+ @return type class.
+ """
+ return self._props.get(PROP_TYPE_CLASS)
+
+ def getTypeID(self):
+ """
+ Get type ID.
+ If the symbol is a type and not a 'typedef', return same as getID().
+ @return type ID.
+ """
+ return self._props.get(PROP_TYPE_ID)
+
+ def getBaseTypeID(self):
+ """
+ Get base type ID.
+ If this symbol is a
+ pointer type - return pointed type
+ array type - return element type
+ function type - return function result type
+ class type - return base class
+ otherwise return None.
+ @return type ID.
+ """
+ return self._props.get(PROP_BASE_TYPE_ID)
+
+ def getIndexTypeID(self):
+ """
+ Get index type ID.
+ If this symbol is a
+ array type - return array index type
+ otherwise return None.
+ @return type ID.
+ """
+ return self._props.get(PROP_INDEX_TYPE_ID)
+
+ def getSize(self):
+ """
+ Return value size of the symbol (or type).
+ @return size in bytes.
+ """
+ return self._props.get(PROP_SIZE, 0)
+
+ def getLength(self):
+ """
+ If symbol is an array type - return number of elements.
+ @return number of elements.
+ """
+ return self._props.get(PROP_LENGTH, 0)
+
+ def getLowerBound(self):
+ """
+ If symbol is an array type - return array index lower bound.
+ @return lower bound.
+ """
+ return self._props.get(PROP_LOWER_BOUND)
+
+ def getUpperBound(self):
+ """
+ If symbol is an array type - return array index upper bound.
+ @return upper bound.
+ """
+ return self._props.get(PROP_UPPER_BOUND)
+
+ def getOffset(self):
+ """
+ Return offset from 'this' for member of class, struct or union.
+ @return offset in bytes.
+ """
+ return self._props.get(PROP_OFFSET, 0)
+
+ def getAddress(self):
+ """
+ Return address of the symbol.
+ @return address or None.
+ """
+ return self._props.get(PROP_ADDRESS)
+
+ def getValue(self):
+ """
+ If symbol is a constant object, return its value.
+ @return symbol value as array of bytes.
+ """
+ return self._props.get(PROP_VALUE)
+
+ def isBigEndian(self):
+ """
+ Get symbol values endianness.
+ @return true if symbol is big-endian.
+ """
+ return self._props.get(PROP_BIG_ENDIAN, False)
+
+ def getRegisterID(self):
+ """
+ Return register ID if the symbol represents a register variable.
+ @return register ID or None.
+ """
+ return self._props.get(PROP_REGISTER)
+
+ def getProperties(self):
+ """
+ Get complete map of context properties.
+ @return map of context properties.
+ """
+ return self._props
+
+class SymbolsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve symbol context info for given symbol ID.
+ @see Symbol
+
+ @param id - symbol context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children IDs for given parent ID.
+ Meaning of the operation depends on parent kind:
+ 1. struct, union, or class type - get fields
+ 2. enumeration type - get enumerators
+
+ @param parent_context_id - parent symbol context ID.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def find(self, context_id, ip, name, done):
+ """
+ Search symbol with given name in given context.
+ The context can be memory space, process, thread or stack frame.
+
+ @param context_id - a search scope.
+ @param ip - instruction pointer - ignored if context_id is a stack frame ID
+ @param name - symbol name.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def findByAddr(self, context_id, addr, done):
+ """
+ Search symbol with given address in given context.
+ The context can be memory space, process, thread or stack frame.
+
+ @param context_id - a search scope.
+ @param addr - symbol address.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def list(self, context_id, done):
+ """
+ List all symbols in given context.
+ The context can be a stack frame.
+
+ @param context_id - a scope.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def findFrameInfo(self, context_id, address, done):
+ """
+ Retrieve stack tracing commands for given instruction address in a context memory.
+ @param context_id - exacutable context ID.
+ @param address - instruction address.
+ @param done - call back interface called when operation is completed.
+ @return - pending command handle.
+ """
+ raise NotImplementedError("Abstract method")
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context properties.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client call back interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param token - command handle
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class DoneFind(object):
+ """
+ Client call back interface for find().
+ """
+ def doneFind(self, token, error, symbol_id):
+ """
+ Called when symbol search is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ @param symbol_id - symbol ID.
+ """
+ pass
+
+class DoneList(object):
+ """
+ Client call back interface for list().
+ """
+ def doneList(self, token, error, symbol_ids):
+ """
+ Called when symbol list retrieval is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ @param symbol_ids - array of symbol IDs.
+ """
+
+
+#
+# Command codes that are used to calculate frame pointer and register values during stack tracing.
+#
+
+# Load a number to the evaluation stack. Command argument is the number.
+CMD_NUMBER = 1
+
+# Load a register value to the evaluation stack. Command argument is the register ID.
+CMD_REGISTER = 2
+
+# Load frame address to the evaluation stack.
+CMD_FP = 3
+
+# Read memory at address on the top of the evaluation stack. Command arguments are
+# the value size (Number) and endianness (Boolean, false - little-endian, true - big-endian).
+CMD_DEREF = 4
+
+# Add two values on top of the evaluation stack
+CMD_ADD = 5
+
+class DoneFindFrameInfo(object):
+ """
+ Client call back interface for findFrameInfo().
+ """
+ def doneFindFrameInfo(self, token, error, address, size, fp_cmds, reg_cmds):
+ """
+ Called when stack tracing information retrieval is done.
+ @param token - command handle.
+ @param error - error description if operation failed, None if succeeded.
+ @param address - start of instruction address range
+ @param size - size of instruction address range
+ @param fp_cmds - commands to calculate stack frame pointer
+ @param reg_cmds - map register IDs -> commands to calculate register values
+ """
+ pass
diff --git a/python/src/tcf/services/sysmonitor.py b/python/src/tcf/services/sysmonitor.py
index 7c313a70a..e758e4ed6 100644
--- a/python/src/tcf/services/sysmonitor.py
+++ b/python/src/tcf/services/sysmonitor.py
@@ -1,402 +1,402 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-This is an optional service that can be implemented by a peer.
-If implemented, the service can be used for monitoring system activity and utilization.
-It provides list of running processes, different process attributes like command line, environment, etc.,
-and some resource utilization data. The service can be used by a client to provide functionality
-similar to Unix 'top' utility or Windows 'Task Manager'.
-"""
-
-from tcf import services
-
-NAME = "SysMonitor"
-
-# Context property names.
-# The TCF context ID"""
-PROP_ID = "ID"
-
-# The TCF parent context ID
-PROP_PARENTID = "ParentID"
-
-# Current working directory of the process
-PROP_CWD = "CWD"
-
-# The process's root directory (as set by chroot)
-PROP_ROOT = "Root"
-
-# User ID of the process owner
-PROP_UID = "UID"
-
-# Group ID of the process owner
-PROP_UGID = "UGID"
-
-# User name of the process owner
-PROP_USERNAME = "UserName"
-
-# Group name of the process owner
-PROP_GROUPNAME = "GroupName"
-
-# System process ID
-PROP_PID = "PID"
-
-# Executable file of the process
-PROP_FILE = "File"
-
-# One character from the string "RSDZTW" where R is running, S is
-# sleeping in an interruptible wait, D is waiting in uninterruptible
-# disk sleep, Z is zombie, T is traced or stopped (on a signal), and W
-# is paging.
-PROP_STATE = "State"
-
-# System ID of the parent process
-PROP_PPID = "PPID"
-
-# The process group ID of the process
-PROP_PGRP = "PGRP"
-
-# The session ID of the process
-PROP_SESSION = "Session"
-
-# The tty the process uses
-PROP_TTY = "TTY"
-
-# The process group ID of the process which currently owns the tty that
-# the process is connected to.
-PROP_TGID = "TGID"
-
-# ID of a process that has attached this process for tracing or debugging
-PROP_TRACERPID = "TracerPID"
-
-# The kernel flags word of the process. Details depend on the kernel
-PROP_FLAGS = "Flags"
-
-# The number of minor faults the process has made which have not
-# required loading a memory page from disk
-PROP_MINFLT = "MinFlt"
-
-# The number of minor faults that the process's waited-for children have made
-PROP_CMINFLT = "CMinFlt"
-
-# The number of major faults the process has made which have required
-# loading a memory page from disk
-PROP_MAJFLT = "MajFlt"
-
-# The number of major faults that the process's waited-for children
-# have made
-PROP_CMAJFLT = "CMajFlt"
-
-# The number of milliseconds that this process has been scheduled in user mode
-PROP_UTIME = "UTime"
-
-# The number of milliseconds that this process has been scheduled in kernel mode
-PROP_STIME = "STime"
-
-# The number of jiffies that this process's waited-for children have
-# been scheduled in user mode
-PROP_CUTIME = "CUTime"
-
-# The number of jiffies that this process's waited-for children have
-# been scheduled in user mode
-PROP_CSTIME = "CSTime"
-
-# The standard nice value
-PROP_PRIORITY = "Priority"
-
-# The nice value
-PROP_NICE = "Nice"
-
-# The time in milliseconds before the next SIGALRM is sent to the process
-# due to an interval timer
-PROP_ITREALVALUE = "ITRealValue"
-
-# The time in milliseconds the process started after system boot
-PROP_STARTTIME = "StartTime"
-
-# Virtual memory size in bytes
-PROP_VSIZE = "VSize"
-
-# Memory pages size in bytes
-PROP_PSIZE = "PSize"
-
-# Resident Set Size: number of pages the process has in real memory,
-# minus used for administrative purposes. This is just the pages which
-# count towards text, data, or stack space. This does not include
-# pages which have not been demand-loaded in, or which are swapped out
-PROP_RSS = "RSS"
-
-# Current limit in bytes on the rss of the process
-PROP_RLIMIT = "RLimit"
-
-# The address above which program text can run
-PROP_CODESTART = "CodeStart"
-
-# The address below which program text can run
-PROP_CODEEND = "CodeEnd"
-
-# The address of the start of the stack
-PROP_STACKSTART = "StackStart"
-
-# The bitmap of pending signals
-PROP_SIGNALS = "Signals"
-
-# The bitmap of blocked signals
-PROP_SIGBLOCK = "SigBlock"
-
-# The bitmap of ignored signals
-PROP_SIGIGNORE = "SigIgnore"
-
-# The bitmap of caught signals
-PROP_SIGCATCH = "SigCatch"
-
-# This is the "channel" in which the process is waiting. It is the
-# address of a system call, and can be looked up in a name list if you
-# need a textual name
-PROP_WCHAN = "WChan"
-
-# Number of pages swapped
-PROP_NSWAP = "NSwap"
-
-# Cumulative NSwap for child processes
-PROP_CNSWAP = "CNSwap"
-
-# Signal to be sent to parent when this process exits
-PROP_EXITSIGNAL = "ExitSignal"
-
-# CPU number last executed on
-PROP_PROCESSOR = "Processor"
-
-# Real-time scheduling priority
-PROP_RTPRIORITY = "RTPriority"
-
-# Scheduling policy
-PROP_POLICY = "Policy"
-
-
-class SysMonitorContext(object):
- """
- A context corresponds to an execution thread, process, address space, etc.
- A context can belong to a parent context. Contexts hierarchy can be simple
- plain list or it can form a tree. It is up to target agent developers to choose
- layout that is most descriptive for a given target. Context IDs are valid across
- all services. In other words, all services access same hierarchy of contexts,
- with same IDs, however, each service accesses its own subset of context's
- attributes and functionality, which is relevant to that service.
- """
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Sys Monitor Context %s]" % self._props
-
- def getID(self):
- """
- Get context ID.
- Same as getProperties().get("ID")
- """
- return self._props.get(PROP_ID)
-
- def getParentID(self):
- """
- Get parent context ID.
- Same as getProperties().get("ParentID")
- """
- return self._props.get(PROP_PARENTID)
-
- def getPGRP(self):
- """
- Get process group ID.
- Same as getProperties().get("PGRP")
- """
- return self._props.get(PROP_PGRP, -1)
-
- def getPID(self):
- """
- Get process ID.
- Same as getProperties().get("PID")
- """
- return self._props.get(PROP_PID, -1)
-
- def getPPID(self):
- """
- Get process parent ID.
- Same as getProperties().get("PPID")
- """
- return self._props.get(PROP_PPID, -1)
-
- def getTGID(self):
- """
- Get process TTY group ID.
- Same as getProperties().get("TGID")
- """
- return self._props.get(PROP_TGID, -1)
-
- def getTracerPID(self):
- """
- Get tracer process ID.
- Same as getProperties().get("TracerPID")
- """
- return self._props.get(PROP_TRACERPID, -1)
-
- def getUID(self):
- """
- Get process owner user ID.
- Same as getProperties().get("UID")
- """
- return self._props.get(PROP_UID, -1)
-
- def getUserName(self):
- """
- Get process owner user name.
- Same as getProperties().get("UserName")
- """
- return self._props.get(PROP_USERNAME)
-
- def getUGID(self):
- """
- Get process owner user group ID.
- Same as getProperties().get("UGID")
- """
- return self._props.get(PROP_UGID, -1)
-
- def getGroupName(self):
- """
- Get process owner user group name.
- Same as getProperties().get("GroupName")
- """
- return self._props.get(PROP_GROUPNAME)
-
- def getState(self):
- """
- Get process state.
- Same as getProperties().get("State")
- """
- return self._props.get(PROP_STATE)
-
- def getVSize(self):
- """
- Get process virtual memory size in bytes.
- Same as getProperties().get("VSize")
- """
- return self._props.get(PROP_VSIZE, -1)
-
- def getPSize(self):
- """
- Get process virtual memory page size in bytes.
- Same as getProperties().get("PSize")
- """
- return self._props.get(PROP_PSIZE, -1)
-
- def getRSS(self):
- """
- Get number of memory pages in process resident set.
- Same as getProperties().get("RSS")
- """
- return self._props.get(PROP_RSS, -1)
-
- def getFile(self):
- """
- Get context executable file.
- Same as getProperties().get("File")
- """
- return self._props.get(PROP_FILE)
-
- def getRoot(self):
- """
- Get context current file system root.
- Same as getProperties().get("Root")
- """
- return self._props.get(PROP_ROOT)
-
- def getCurrentWorkingDirectory(self):
- """
- Get context current working directory.
- Same as getProperties().get("CWD")
- """
- return self._props.get(PROP_CWD)
-
- def getProperties(self):
- """
- Get all available context properties.
- @return Map 'property name' -> 'property value'
- """
- return self._props
-
-
-class SysMonitorService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context info for given context ID.
-
- @param id - context ID.
- @param done - callback interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getChildren(self, parent_context_id, done):
- """
- Retrieve children of given context.
-
- @param parent_context_id - parent context ID. Can be None -
- to retrieve top level of the hierarchy, or one of context IDs retrieved
- by previous getContext or getChildren commands.
- @param done - callback interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def getCommandLine(self, id, done):
- """
- Get context command line.
- """
- raise NotImplementedError("Abstract method")
-
- def getEnvironment(self, id, done):
- """
- Get context environment variables.
- """
- raise NotImplementedError("Abstract method")
-
-
-class DoneGetContext(object):
- """
- Client callback interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when context data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneGetChildren(object):
- """
- Client callback interface for getChildren().
- """
- def doneGetChildren(self, token, error, context_ids):
- """
- Called when context list retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context_ids - array of available context IDs.
- """
- pass
-
-class DoneGetCommandLine(object):
- def doneGetCommandLine(self, token, error, cmd_line):
- pass
-
-class DoneGetEnvironment(object):
- def doneGetEnvironment(self, token, error, environment):
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+This is an optional service that can be implemented by a peer.
+If implemented, the service can be used for monitoring system activity and utilization.
+It provides list of running processes, different process attributes like command line, environment, etc.,
+and some resource utilization data. The service can be used by a client to provide functionality
+similar to Unix 'top' utility or Windows 'Task Manager'.
+"""
+
+from tcf import services
+
+NAME = "SysMonitor"
+
+# Context property names.
+# The TCF context ID"""
+PROP_ID = "ID"
+
+# The TCF parent context ID
+PROP_PARENTID = "ParentID"
+
+# Current working directory of the process
+PROP_CWD = "CWD"
+
+# The process's root directory (as set by chroot)
+PROP_ROOT = "Root"
+
+# User ID of the process owner
+PROP_UID = "UID"
+
+# Group ID of the process owner
+PROP_UGID = "UGID"
+
+# User name of the process owner
+PROP_USERNAME = "UserName"
+
+# Group name of the process owner
+PROP_GROUPNAME = "GroupName"
+
+# System process ID
+PROP_PID = "PID"
+
+# Executable file of the process
+PROP_FILE = "File"
+
+# One character from the string "RSDZTW" where R is running, S is
+# sleeping in an interruptible wait, D is waiting in uninterruptible
+# disk sleep, Z is zombie, T is traced or stopped (on a signal), and W
+# is paging.
+PROP_STATE = "State"
+
+# System ID of the parent process
+PROP_PPID = "PPID"
+
+# The process group ID of the process
+PROP_PGRP = "PGRP"
+
+# The session ID of the process
+PROP_SESSION = "Session"
+
+# The tty the process uses
+PROP_TTY = "TTY"
+
+# The process group ID of the process which currently owns the tty that
+# the process is connected to.
+PROP_TGID = "TGID"
+
+# ID of a process that has attached this process for tracing or debugging
+PROP_TRACERPID = "TracerPID"
+
+# The kernel flags word of the process. Details depend on the kernel
+PROP_FLAGS = "Flags"
+
+# The number of minor faults the process has made which have not
+# required loading a memory page from disk
+PROP_MINFLT = "MinFlt"
+
+# The number of minor faults that the process's waited-for children have made
+PROP_CMINFLT = "CMinFlt"
+
+# The number of major faults the process has made which have required
+# loading a memory page from disk
+PROP_MAJFLT = "MajFlt"
+
+# The number of major faults that the process's waited-for children
+# have made
+PROP_CMAJFLT = "CMajFlt"
+
+# The number of milliseconds that this process has been scheduled in user mode
+PROP_UTIME = "UTime"
+
+# The number of milliseconds that this process has been scheduled in kernel mode
+PROP_STIME = "STime"
+
+# The number of jiffies that this process's waited-for children have
+# been scheduled in user mode
+PROP_CUTIME = "CUTime"
+
+# The number of jiffies that this process's waited-for children have
+# been scheduled in user mode
+PROP_CSTIME = "CSTime"
+
+# The standard nice value
+PROP_PRIORITY = "Priority"
+
+# The nice value
+PROP_NICE = "Nice"
+
+# The time in milliseconds before the next SIGALRM is sent to the process
+# due to an interval timer
+PROP_ITREALVALUE = "ITRealValue"
+
+# The time in milliseconds the process started after system boot
+PROP_STARTTIME = "StartTime"
+
+# Virtual memory size in bytes
+PROP_VSIZE = "VSize"
+
+# Memory pages size in bytes
+PROP_PSIZE = "PSize"
+
+# Resident Set Size: number of pages the process has in real memory,
+# minus used for administrative purposes. This is just the pages which
+# count towards text, data, or stack space. This does not include
+# pages which have not been demand-loaded in, or which are swapped out
+PROP_RSS = "RSS"
+
+# Current limit in bytes on the rss of the process
+PROP_RLIMIT = "RLimit"
+
+# The address above which program text can run
+PROP_CODESTART = "CodeStart"
+
+# The address below which program text can run
+PROP_CODEEND = "CodeEnd"
+
+# The address of the start of the stack
+PROP_STACKSTART = "StackStart"
+
+# The bitmap of pending signals
+PROP_SIGNALS = "Signals"
+
+# The bitmap of blocked signals
+PROP_SIGBLOCK = "SigBlock"
+
+# The bitmap of ignored signals
+PROP_SIGIGNORE = "SigIgnore"
+
+# The bitmap of caught signals
+PROP_SIGCATCH = "SigCatch"
+
+# This is the "channel" in which the process is waiting. It is the
+# address of a system call, and can be looked up in a name list if you
+# need a textual name
+PROP_WCHAN = "WChan"
+
+# Number of pages swapped
+PROP_NSWAP = "NSwap"
+
+# Cumulative NSwap for child processes
+PROP_CNSWAP = "CNSwap"
+
+# Signal to be sent to parent when this process exits
+PROP_EXITSIGNAL = "ExitSignal"
+
+# CPU number last executed on
+PROP_PROCESSOR = "Processor"
+
+# Real-time scheduling priority
+PROP_RTPRIORITY = "RTPriority"
+
+# Scheduling policy
+PROP_POLICY = "Policy"
+
+
+class SysMonitorContext(object):
+ """
+ A context corresponds to an execution thread, process, address space, etc.
+ A context can belong to a parent context. Contexts hierarchy can be simple
+ plain list or it can form a tree. It is up to target agent developers to choose
+ layout that is most descriptive for a given target. Context IDs are valid across
+ all services. In other words, all services access same hierarchy of contexts,
+ with same IDs, however, each service accesses its own subset of context's
+ attributes and functionality, which is relevant to that service.
+ """
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Sys Monitor Context %s]" % self._props
+
+ def getID(self):
+ """
+ Get context ID.
+ Same as getProperties().get("ID")
+ """
+ return self._props.get(PROP_ID)
+
+ def getParentID(self):
+ """
+ Get parent context ID.
+ Same as getProperties().get("ParentID")
+ """
+ return self._props.get(PROP_PARENTID)
+
+ def getPGRP(self):
+ """
+ Get process group ID.
+ Same as getProperties().get("PGRP")
+ """
+ return self._props.get(PROP_PGRP, -1)
+
+ def getPID(self):
+ """
+ Get process ID.
+ Same as getProperties().get("PID")
+ """
+ return self._props.get(PROP_PID, -1)
+
+ def getPPID(self):
+ """
+ Get process parent ID.
+ Same as getProperties().get("PPID")
+ """
+ return self._props.get(PROP_PPID, -1)
+
+ def getTGID(self):
+ """
+ Get process TTY group ID.
+ Same as getProperties().get("TGID")
+ """
+ return self._props.get(PROP_TGID, -1)
+
+ def getTracerPID(self):
+ """
+ Get tracer process ID.
+ Same as getProperties().get("TracerPID")
+ """
+ return self._props.get(PROP_TRACERPID, -1)
+
+ def getUID(self):
+ """
+ Get process owner user ID.
+ Same as getProperties().get("UID")
+ """
+ return self._props.get(PROP_UID, -1)
+
+ def getUserName(self):
+ """
+ Get process owner user name.
+ Same as getProperties().get("UserName")
+ """
+ return self._props.get(PROP_USERNAME)
+
+ def getUGID(self):
+ """
+ Get process owner user group ID.
+ Same as getProperties().get("UGID")
+ """
+ return self._props.get(PROP_UGID, -1)
+
+ def getGroupName(self):
+ """
+ Get process owner user group name.
+ Same as getProperties().get("GroupName")
+ """
+ return self._props.get(PROP_GROUPNAME)
+
+ def getState(self):
+ """
+ Get process state.
+ Same as getProperties().get("State")
+ """
+ return self._props.get(PROP_STATE)
+
+ def getVSize(self):
+ """
+ Get process virtual memory size in bytes.
+ Same as getProperties().get("VSize")
+ """
+ return self._props.get(PROP_VSIZE, -1)
+
+ def getPSize(self):
+ """
+ Get process virtual memory page size in bytes.
+ Same as getProperties().get("PSize")
+ """
+ return self._props.get(PROP_PSIZE, -1)
+
+ def getRSS(self):
+ """
+ Get number of memory pages in process resident set.
+ Same as getProperties().get("RSS")
+ """
+ return self._props.get(PROP_RSS, -1)
+
+ def getFile(self):
+ """
+ Get context executable file.
+ Same as getProperties().get("File")
+ """
+ return self._props.get(PROP_FILE)
+
+ def getRoot(self):
+ """
+ Get context current file system root.
+ Same as getProperties().get("Root")
+ """
+ return self._props.get(PROP_ROOT)
+
+ def getCurrentWorkingDirectory(self):
+ """
+ Get context current working directory.
+ Same as getProperties().get("CWD")
+ """
+ return self._props.get(PROP_CWD)
+
+ def getProperties(self):
+ """
+ Get all available context properties.
+ @return Map 'property name' -> 'property value'
+ """
+ return self._props
+
+
+class SysMonitorService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+
+ @param id - context ID.
+ @param done - callback interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getChildren(self, parent_context_id, done):
+ """
+ Retrieve children of given context.
+
+ @param parent_context_id - parent context ID. Can be None -
+ to retrieve top level of the hierarchy, or one of context IDs retrieved
+ by previous getContext or getChildren commands.
+ @param done - callback interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getCommandLine(self, id, done):
+ """
+ Get context command line.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def getEnvironment(self, id, done):
+ """
+ Get context environment variables.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class DoneGetContext(object):
+ """
+ Client callback interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when context data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneGetChildren(object):
+ """
+ Client callback interface for getChildren().
+ """
+ def doneGetChildren(self, token, error, context_ids):
+ """
+ Called when context list retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context_ids - array of available context IDs.
+ """
+ pass
+
+class DoneGetCommandLine(object):
+ def doneGetCommandLine(self, token, error, cmd_line):
+ pass
+
+class DoneGetEnvironment(object):
+ def doneGetEnvironment(self, token, error, environment):
+ pass
diff --git a/python/src/tcf/services/terminals.py b/python/src/tcf/services/terminals.py
index a41d90a67..6c1d5a6f7 100644
--- a/python/src/tcf/services/terminals.py
+++ b/python/src/tcf/services/terminals.py
@@ -1,222 +1,222 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-ITerminalsService allows to launch a new terminal on the remote target system.
-"""
-
-from tcf import services
-
-# This service name, as it appears on the wire - a TCF name of the service.
-NAME = "Terminals"
-
-# Context property names.
-# The TCF context ID
-PROP_ID = "ID",
-
-# The process ID of the login process of the terminal
-PROP_PROCESS_ID = "ProcessID",
-
-# The PTY type
-PROP_PTY_TYPE = "PtyType",
-
-# terminal encoding
-PROP_ENCODING = "Encoding",
-
-# window width size
-PROP_WIDTH = "Width",
-
-# window height size
-PROP_HEIGHT = "Height",
-
-# Process standard input stream ID
-PROP_STDIN_ID = "StdInID",
-
-# Process standard output stream ID
-PROP_STDOUT_ID = "StdOutID",
-
-# Process standard error stream ID
-PROP_STDERR_ID = "StdErrID"
-
-class TerminalContext(object):
- def __init__(self, props):
- self._props = props or {}
-
- def __str__(self):
- return "[Terminals Context %s]" % str(self._props)
-
- def getID(self):
- """
- Get context ID.
- Same as getProperties().get("ID")
- """
- return self._props.get(PROP_ID)
-
- def getProcessID(self):
- """
- Get process ID of the login process of the terminal.
- Same as getProperties().get("ProcessID")
- """
- return self._props.get(PROP_PROCESS_ID)
-
- def getPtyType(self):
- """
- Get terminal type.
- Same as getProperties().get("PtyType")
- """
- return self._props.get(PROP_PTY_TYPE)
-
- def getEncoding(self):
- """
- Get encoding.
- Same as getProperties().get("Encoding")
- """
- return self._props.get(PROP_ENCODING)
-
- def getWidth(self):
- """
- Get width.
- Same as getProperties().get("Width")
- """
- return self._props.get(PROP_WIDTH)
-
- def getHeight(self):
- """
- Get height.
- Same as getProperties().get("Height")
- """
- return self._props.get(PROP_HEIGHT)
-
- def getProperties(self):
- """
- Get all available context properties.
- @return Map 'property name' -> 'property value'
- """
- return self._props
-
- def exit(self, done):
- """
- Exit the terminal.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
-class TerminalsService(services.Service):
- def getName(self):
- return NAME
-
- def getContext(self, id, done):
- """
- Retrieve context info for given context ID.
- A context corresponds to an terminal.
- Context IDs are valid across TCF services, so it is allowed to issue
- 'ITerminals.getContext' command with a context that was obtained,
- for example, from Memory service.
- However, 'ITerminals.getContext' is supposed to return only terminal specific data,
- If the ID is not a terminal ID, 'ITerminals.getContext' may not return any
- useful information
-
- @param id - context ID.
- @param done - call back interface called when operation is completed.
- """
- raise NotImplementedError("Abstract method")
-
- def launch(self, type, encoding, environment, done):
- """
- Launch a new terminal to remote machine.
- @param type - requested terminal type for the new terminal.
- @param encoding - requested encoding for the new terminal.
- @param environment - Array of environment variable strings.
- if None then default set of environment variables will be used.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def setWinSize(self, context_id, newWidth, newHeight, done):
- """
- Set the terminal widows size
- @param context_id - context ID.
- @param signal - signal code.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def exit(self, context_id, done):
- """
- Exit a terminal.
- @param context_id - context ID.
- @param done - call back interface called when operation is completed.
- @return pending command handle, can be used to cancel the command.
- """
- raise NotImplementedError("Abstract method")
-
- def addListener(self, listener):
- """
- Add terminals service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
- def removeListener(self, listener):
- """
- Remove terminals service event listener.
- @param listener - event listener implementation.
- """
- raise NotImplementedError("Abstract method")
-
-
-class DoneGetContext(object):
- """
- Client call back interface for getContext().
- """
- def doneGetContext(self, token, error, context):
- """
- Called when contexts data retrieval is done.
- @param error - error description if operation failed, None if succeeded.
- @param context - context data.
- """
- pass
-
-class DoneCommand(object):
- def doneCommand(self, token, error):
- pass
-
-class DoneLaunch(object):
- """
- Call-back interface to be called when "start" command is complete.
- """
- def doneLaunch(self, token, error, terminal):
- pass
-
-class TerminalsListener(object):
- """
- Process event listener is notified when a terminal exits.
- Event are reported only for terminals that were started by 'launch' command.
- """
- def exited(self, terminal_id, exit_code):
- """
- Called when a terminal exits.
- @param terminal_id - terminal context ID
- @param exit_code - terminal exit code
- """
- pass
-
- def winSizeChanged (self, terminal_id, newWidth, newHeight):
- """
- Called when a terminal exits.
- @param terminal_id - terminal context ID
- @param newWidth - new terminal width
- @param newHeight - new terminal height
- """
- pass
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+ITerminalsService allows to launch a new terminal on the remote target system.
+"""
+
+from tcf import services
+
+# This service name, as it appears on the wire - a TCF name of the service.
+NAME = "Terminals"
+
+# Context property names.
+# The TCF context ID
+PROP_ID = "ID",
+
+# The process ID of the login process of the terminal
+PROP_PROCESS_ID = "ProcessID",
+
+# The PTY type
+PROP_PTY_TYPE = "PtyType",
+
+# terminal encoding
+PROP_ENCODING = "Encoding",
+
+# window width size
+PROP_WIDTH = "Width",
+
+# window height size
+PROP_HEIGHT = "Height",
+
+# Process standard input stream ID
+PROP_STDIN_ID = "StdInID",
+
+# Process standard output stream ID
+PROP_STDOUT_ID = "StdOutID",
+
+# Process standard error stream ID
+PROP_STDERR_ID = "StdErrID"
+
+class TerminalContext(object):
+ def __init__(self, props):
+ self._props = props or {}
+
+ def __str__(self):
+ return "[Terminals Context %s]" % str(self._props)
+
+ def getID(self):
+ """
+ Get context ID.
+ Same as getProperties().get("ID")
+ """
+ return self._props.get(PROP_ID)
+
+ def getProcessID(self):
+ """
+ Get process ID of the login process of the terminal.
+ Same as getProperties().get("ProcessID")
+ """
+ return self._props.get(PROP_PROCESS_ID)
+
+ def getPtyType(self):
+ """
+ Get terminal type.
+ Same as getProperties().get("PtyType")
+ """
+ return self._props.get(PROP_PTY_TYPE)
+
+ def getEncoding(self):
+ """
+ Get encoding.
+ Same as getProperties().get("Encoding")
+ """
+ return self._props.get(PROP_ENCODING)
+
+ def getWidth(self):
+ """
+ Get width.
+ Same as getProperties().get("Width")
+ """
+ return self._props.get(PROP_WIDTH)
+
+ def getHeight(self):
+ """
+ Get height.
+ Same as getProperties().get("Height")
+ """
+ return self._props.get(PROP_HEIGHT)
+
+ def getProperties(self):
+ """
+ Get all available context properties.
+ @return Map 'property name' -> 'property value'
+ """
+ return self._props
+
+ def exit(self, done):
+ """
+ Exit the terminal.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+class TerminalsService(services.Service):
+ def getName(self):
+ return NAME
+
+ def getContext(self, id, done):
+ """
+ Retrieve context info for given context ID.
+ A context corresponds to an terminal.
+ Context IDs are valid across TCF services, so it is allowed to issue
+ 'ITerminals.getContext' command with a context that was obtained,
+ for example, from Memory service.
+ However, 'ITerminals.getContext' is supposed to return only terminal specific data,
+ If the ID is not a terminal ID, 'ITerminals.getContext' may not return any
+ useful information
+
+ @param id - context ID.
+ @param done - call back interface called when operation is completed.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def launch(self, type, encoding, environment, done):
+ """
+ Launch a new terminal to remote machine.
+ @param type - requested terminal type for the new terminal.
+ @param encoding - requested encoding for the new terminal.
+ @param environment - Array of environment variable strings.
+ if None then default set of environment variables will be used.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def setWinSize(self, context_id, newWidth, newHeight, done):
+ """
+ Set the terminal widows size
+ @param context_id - context ID.
+ @param signal - signal code.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def exit(self, context_id, done):
+ """
+ Exit a terminal.
+ @param context_id - context ID.
+ @param done - call back interface called when operation is completed.
+ @return pending command handle, can be used to cancel the command.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def addListener(self, listener):
+ """
+ Add terminals service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def removeListener(self, listener):
+ """
+ Remove terminals service event listener.
+ @param listener - event listener implementation.
+ """
+ raise NotImplementedError("Abstract method")
+
+
+class DoneGetContext(object):
+ """
+ Client call back interface for getContext().
+ """
+ def doneGetContext(self, token, error, context):
+ """
+ Called when contexts data retrieval is done.
+ @param error - error description if operation failed, None if succeeded.
+ @param context - context data.
+ """
+ pass
+
+class DoneCommand(object):
+ def doneCommand(self, token, error):
+ pass
+
+class DoneLaunch(object):
+ """
+ Call-back interface to be called when "start" command is complete.
+ """
+ def doneLaunch(self, token, error, terminal):
+ pass
+
+class TerminalsListener(object):
+ """
+ Process event listener is notified when a terminal exits.
+ Event are reported only for terminals that were started by 'launch' command.
+ """
+ def exited(self, terminal_id, exit_code):
+ """
+ Called when a terminal exits.
+ @param terminal_id - terminal context ID
+ @param exit_code - terminal exit code
+ """
+ pass
+
+ def winSizeChanged (self, terminal_id, newWidth, newHeight):
+ """
+ Called when a terminal exits.
+ @param terminal_id - terminal context ID
+ @param newWidth - new terminal width
+ @param newHeight - new terminal height
+ """
+ pass
diff --git a/python/src/tcf/shell.py b/python/src/tcf/shell.py
index 38942fe30..ea7f1f177 100644
--- a/python/src/tcf/shell.py
+++ b/python/src/tcf/shell.py
@@ -1,101 +1,101 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"""
-Simple interactive shell for TCF. This is basically a Python interpreter with a few
-TCF extensions.
-
-Usage:
- python -m tcf.shell
-
-Commands:
- peers - Print discovered peers
- connect(params) - Connect to TCF peer, params = "<protocol>:<host>:<port>"
- cmd.<service>.<command<(args)
- - Send command to remote service and return result
- disconnect - Disconnect from peer
- events.record(<service>)
- - Start recording events for service
- events - Print last recorded events
- events.stop([<service>])
- - Stop recording for service or for all services
-"""
-
-import code, sys, os
-try:
- import tcf
-except ImportError:
- # add current dir to path
- sys.path.insert(0, os.getcwd())
- import tcf
-from tcf.util import sync, event
-from tcf import protocol, channel
-
-class print_peers:
- "Print list of discovered peers"
- def __call__(self):
- return tcf.peers()
- def __repr__(self):
- peers = tcf.peers()
- return '\n'.join(map(lambda p: "%s, %s" % (p.getID(), p.getName()), peers.values()))
-
-class Shell(code.InteractiveConsole, protocol.ChannelOpenListener, channel.ChannelListener):
- def __init__(self):
- locals = {
- "connect" : tcf.connect,
- "peers" : print_peers()
- }
- protocol.startEventQueue()
- protocol.startDiscovery()
- protocol.invokeAndWait(protocol.addChannelOpenListener, self)
- code.InteractiveConsole.__init__(self, locals)
- def interact(self, banner=None):
- try:
- try:
- ps1 = sys.ps1 #@UndefinedVariable
- except AttributeError:
- ps1 = None
- sys.ps1 = "tcf> "
- super(Shell, self).interact(banner)
- finally:
- if ps1:
- sys.ps1 = ps1
- else:
- del sys.ps1
- protocol.invokeLater(protocol.removeChannelOpenListener, self)
- protocol.shutdownDiscovery()
- protocol.getEventQueue().shutdown()
- def onChannelOpen(self, channel):
- wrapper = sync.DispatchWrapper(channel)
- self.locals["channel"] = wrapper
- self.locals["disconnect"] = wrapper.close
- self.locals["cmd"] = sync.CommandControl(channel, interactive=True)
- self.locals["events"] = event.EventRecorder(channel)
- protocol.invokeAndWait(protocol.removeChannelOpenListener, self)
- wrapper.addChannelListener(self)
- def onChannelClosed(self, error):
- del self.locals["channel"]
- del self.locals["cmd"]
- del self.locals["disconnect"]
- del self.locals["events"]
- protocol.addChannelOpenListener(self)
-
-def interact():
- try:
- # enable commandline editing if available
- import readline #@UnusedImport
- except ImportError:
- pass
- shell = Shell()
- shell.interact("TCF Shell")
-
-if __name__ == "__main__":
- interact()
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"""
+Simple interactive shell for TCF. This is basically a Python interpreter with a few
+TCF extensions.
+
+Usage:
+ python -m tcf.shell
+
+Commands:
+ peers - Print discovered peers
+ connect(params) - Connect to TCF peer, params = "<protocol>:<host>:<port>"
+ cmd.<service>.<command<(args)
+ - Send command to remote service and return result
+ disconnect - Disconnect from peer
+ events.record(<service>)
+ - Start recording events for service
+ events - Print last recorded events
+ events.stop([<service>])
+ - Stop recording for service or for all services
+"""
+
+import code, sys, os
+try:
+ import tcf
+except ImportError:
+ # add current dir to path
+ sys.path.insert(0, os.getcwd())
+ import tcf
+from tcf.util import sync, event
+from tcf import protocol, channel
+
+class print_peers:
+ "Print list of discovered peers"
+ def __call__(self):
+ return tcf.peers()
+ def __repr__(self):
+ peers = tcf.peers()
+ return '\n'.join(map(lambda p: "%s, %s" % (p.getID(), p.getName()), peers.values()))
+
+class Shell(code.InteractiveConsole, protocol.ChannelOpenListener, channel.ChannelListener):
+ def __init__(self):
+ locals = {
+ "connect" : tcf.connect,
+ "peers" : print_peers()
+ }
+ protocol.startEventQueue()
+ protocol.startDiscovery()
+ protocol.invokeAndWait(protocol.addChannelOpenListener, self)
+ code.InteractiveConsole.__init__(self, locals)
+ def interact(self, banner=None):
+ try:
+ try:
+ ps1 = sys.ps1 #@UndefinedVariable
+ except AttributeError:
+ ps1 = None
+ sys.ps1 = "tcf> "
+ super(Shell, self).interact(banner)
+ finally:
+ if ps1:
+ sys.ps1 = ps1
+ else:
+ del sys.ps1
+ protocol.invokeLater(protocol.removeChannelOpenListener, self)
+ protocol.shutdownDiscovery()
+ protocol.getEventQueue().shutdown()
+ def onChannelOpen(self, channel):
+ wrapper = sync.DispatchWrapper(channel)
+ self.locals["channel"] = wrapper
+ self.locals["disconnect"] = wrapper.close
+ self.locals["cmd"] = sync.CommandControl(channel, interactive=True)
+ self.locals["events"] = event.EventRecorder(channel)
+ protocol.invokeAndWait(protocol.removeChannelOpenListener, self)
+ wrapper.addChannelListener(self)
+ def onChannelClosed(self, error):
+ del self.locals["channel"]
+ del self.locals["cmd"]
+ del self.locals["disconnect"]
+ del self.locals["events"]
+ protocol.addChannelOpenListener(self)
+
+def interact():
+ try:
+ # enable commandline editing if available
+ import readline #@UnusedImport
+ except ImportError:
+ pass
+ shell = Shell()
+ shell.interact("TCF Shell")
+
+if __name__ == "__main__":
+ interact()
diff --git a/python/src/tcf/tests/BasicTests.py b/python/src/tcf/tests/BasicTests.py
index 24b92939c..83c2847ff 100644
--- a/python/src/tcf/tests/BasicTests.py
+++ b/python/src/tcf/tests/BasicTests.py
@@ -1,660 +1,660 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import sys, time, threading, atexit
-import tcf
-from tcf import protocol, channel, errors
-from tcf.util import sync
-
-__TRACE = False
-class TraceListener(channel.TraceListener):
- def onMessageReceived(self, type, token, service, name, data):
- print "<<<", type, token, service, name, data
- def onMessageSent(self, type, token, service, name, data):
- print ">>>", type, token, service, name, data
- def onChannelClosed(self, error):
- print>>sys.stderr, "*** closed ***", error
-
-_suspended = []
-_memory = []
-
-def test():
- protocol.startEventQueue()
- atexit.register(protocol.getEventQueue().shutdown)
- #testTimer()
- try:
- c = tcf.connect("TCP:127.0.0.1:1534")
- except Exception as e:
- protocol.log(e)
- sys.exit()
- assert c.state == channel.STATE_OPEN
- if __TRACE: protocol.invokeLater(c.addTraceListener, TraceListener())
- def printServices():
- print "services=", c.getRemoteServices()
- protocol.invokeLater(printServices)
-
- try:
- testRunControl(c)
- testStackTrace(c)
- testDisassembly(c)
- testBreakpoints(c)
- testSymbols(c)
- testRegisters(c)
- testExpressions(c)
- testLineNumbers(c)
- testSyncCommands(c)
- testTasks(c)
- testEvents(c)
- testDataCache(c)
- testProcesses(c)
- testFileSystem(c)
- testMemory(c)
- testMemoryMap(c)
- testPathMap(c)
- testSysMonitor(c)
- except Exception as e:
- protocol.log(e)
-
- if c.state == channel.STATE_OPEN:
- time.sleep(5)
- protocol.invokeLater(c.close)
- time.sleep(2)
-
-
-def testTimer():
- cond = threading.Condition()
- def countdown(left):
- if left == 0:
- print "Ignition sequence started!"
- with cond:
- cond.notify()
- return
- print "%d seconds to go" % left
- sys.stdout.flush()
- protocol.invokeLaterWithDelay(1000, countdown, left - 1)
- with cond:
- protocol.invokeLaterWithDelay(0, countdown, 10)
- cond.wait(15)
-
-def testRunControl(c):
- lock = threading.Condition()
- from tcf.services import runcontrol
- def getContexts():
- rctrl = c.getRemoteService(runcontrol.NAME)
- pending = []
- class DoneGetContext(runcontrol.DoneGetContext):
- def doneGetContext(self, token, error, context):
- pending.remove(token)
- if error:
- protocol.log("Error from RunControl.getContext", error)
- else:
- print context
- class DoneGetState(runcontrol.DoneGetState):
- def doneGetState(self, token, error, suspended, pc, reason, params):
- pending.remove(token)
- if error:
- protocol.log("Error from RunControl.getState", error)
- else:
- print "suspended: ", suspended
- print "pc: ", pc
- print "reason: ", reason
- print "params: ", params
- if suspended:
- _suspended.append(context.getID())
- if len(pending) == 0:
- with lock:
- lock.notify()
- if context and context.hasState(): pending.append(context.getState(DoneGetState()))
- if len(pending) == 0:
- with lock:
- lock.notify()
- class DoneGetChildren(runcontrol.DoneGetChildren):
- def doneGetChildren(self, token, error, context_ids):
- pending.remove(token)
- if error:
- protocol.log("Error from RunControl.GetChildren", error)
- else:
- for c in context_ids:
- pending.append(rctrl.getContext(c, DoneGetContext()))
- pending.append(rctrl.getChildren(c, self))
- if len(pending) == 0:
- with lock:
- lock.notify()
- pending.append(rctrl.getChildren(None, DoneGetChildren()))
- with lock:
- protocol.invokeLater(getContexts)
- lock.wait(5)
- def listenerTest():
- rc = c.getRemoteService(runcontrol.NAME)
- class RCListener(runcontrol.RunControlListener):
- def contextSuspended(self, *args):
- print "context suspended: ", args
- rc.removeListener(self)
- def contextResumed(self, *args):
- print "context resumed: ", args
- def containerSuspended(self, *args):
- print "container suspended:", args
- rc.removeListener(self)
- def containerResumed(self, *args):
- print "container resumed:", args
- rc.addListener(RCListener())
- class DoneGetContext(runcontrol.DoneGetContext):
- def doneGetContext(self, token, error, context):
- if error:
- protocol.log("Error from RunControl.getContext", error)
- with lock: lock.notify()
- return
- class DoneResume(runcontrol.DoneCommand):
- def doneCommand(self, token, error):
- if error:
- protocol.log("Error from RunControl.resume", error)
- else:
- context.suspend(runcontrol.DoneCommand())
- with lock: lock.notify()
- context.resume(runcontrol.RM_RESUME, 1, None, DoneResume())
- rc.getContext(_suspended[0], DoneGetContext())
-
- if _suspended:
- with lock:
- protocol.invokeLater(listenerTest)
- lock.wait(5)
-
-def testBreakpoints(c):
- from tcf.services import breakpoints
- def testBPQuery():
- bps = c.getRemoteService(breakpoints.NAME)
- def doneGetIDs(token, error, ids):
- if error:
- protocol.log("Error from Breakpoints.getIDs", error)
- return
- print "Breakpoints :", ids
- def doneGetProperties(token, error, props):
- if error:
- protocol.log("Error from Breakpoints.getProperties", error)
- return
- print "Breakpoint Properties: ", props
- def doneGetStatus(token, error, props):
- if error:
- protocol.log("Error from Breakpoints.getStatus", error)
- return
- print "Breakpoint Status: ", props
- for id in ids:
- bps.getProperties(id, doneGetProperties)
- bps.getStatus(id, doneGetStatus)
- bps.getIDs(doneGetIDs)
- protocol.invokeLater(testBPQuery)
- def testBPSet():
- bpsvc = c.getRemoteService(breakpoints.NAME)
- class BPListener(breakpoints.BreakpointsListener):
- def breakpointStatusChanged(self, id, status):
- print "breakpointStatusChanged", id, status
- def contextAdded(self, bps):
- print "breakpointAdded", bps
- bpsvc.removeListener(self)
- def contextChanged(self, bps):
- print "breakpointChanged", bps
- def contextRemoved(self, ids):
- print "breakpointRemoved", ids
- bpsvc.addListener(BPListener())
- def doneSet(token, error):
- if error:
- protocol.log("Error from Breakpoints.set", error)
- return
- bp = {
- breakpoints.PROP_ID : "python:1",
- breakpoints.PROP_ENABLED : True,
- breakpoints.PROP_LOCATION : "sysClkRateGet"
- }
- bpsvc.set([bp], doneSet)
- protocol.invokeLater(testBPSet)
-
-def testStackTrace(c):
- from tcf.services import stacktrace
- def stackTest(ctx_id):
- stack = c.getRemoteService(stacktrace.NAME)
- class DoneGetChildren(stacktrace.DoneGetChildren):
- def doneGetChildren(self, token, error, ctx_ids):
- if error:
- protocol.log("Error from StackTrace.getChildren", error)
- return
- class DoneGetContext(stacktrace.DoneGetContext):
- def doneGetContext(self, token, error, ctxs):
- if error:
- protocol.log("Error from StackTrace.getContext", error)
- return
- if ctxs:
- for ctx in ctxs:
- print ctx
- stack.getContext(ctx_ids, DoneGetContext())
- stack.getChildren(ctx_id, DoneGetChildren())
- for ctx_id in _suspended:
- protocol.invokeLater(stackTest, ctx_id)
-
-def testDisassembly(c):
- if not _suspended: return
- ctl = sync.CommandControl(c)
- try:
- dis = ctl.Disassembly
- except AttributeError:
- # no Disassembly service
- return
- for ctx_id in _suspended:
- frames = ctl.StackTrace.getChildren(ctx_id).get()
- if frames:
- frameData = ctl.StackTrace.getContext(frames).get()
- if frameData:
- addr = frameData[0].get("IP")
- if addr:
- print "Disassemble context %s from 0x%x" % (ctx_id, addr)
- lines = dis.disassemble(ctx_id, addr, 256, None).get()
- if lines:
- for line in lines:
- print line
-
-def testSymbols(c):
- from tcf.services import symbols
- def symTest(ctx_id):
- syms = c.getRemoteService(symbols.NAME)
- class DoneList(symbols.DoneList):
- def doneList(self, token, error, ctx_ids):
- if error:
- protocol.log("Error from Symbols.list", error)
- return
- class DoneGetContext(symbols.DoneGetContext):
- def doneGetContext(self, token, error, ctx):
- if error:
- protocol.log("Error from Symbols.getContext", error)
- return
- print ctx
- if ctx_ids:
- for ctx_id in ctx_ids:
- syms.getContext(ctx_id, DoneGetContext())
- syms.list(ctx_id, DoneList())
- for ctx_id in _suspended:
- protocol.invokeLater(symTest, ctx_id)
-
-def testRegisters(c):
- if not _suspended: return
- from tcf.services import registers
- lock = threading.Condition()
- def regTest(ctx_id):
- regs = c.getRemoteService(registers.NAME)
- pending = []
- def onDone():
- with lock: lock.notify()
- class DoneGetChildren(registers.DoneGetChildren):
- def doneGetChildren(self, token, error, ctx_ids):
- pending.remove(token)
- if error:
- protocol.log("Error from Registers.getChildren", error)
- if not pending:
- onDone()
- class DoneGetContext(registers.DoneGetContext):
- def doneGetContext(self, token, error, ctx):
- pending.remove(token)
- if error:
- protocol.log("Error from Registers.getContext", error)
- else:
- print ctx
- if ctx.isReadable() and not ctx.isReadOnce() and ctx.getSize() >= 2:
- locs = []
- locs.append(registers.Location(ctx.getID(), 0, 1))
- locs.append(registers.Location(ctx.getID(), 1, 1))
- class DoneGetM(registers.DoneGet):
- def doneGet(self, token, error, value):
- pending.remove(token)
- if error:
- protocol.log("Error from Registers.getm", error)
- else:
- print "getm", ctx.getID(), map(ord, value)
- if not pending:
- onDone()
- pending.append(regs.getm(locs, DoneGetM()))
- if ctx.isWriteable() and not ctx.isWriteOnce() and ctx.getSize() >= 2:
- locs = []
- locs.append(registers.Location(ctx.getID(), 0, 1))
- locs.append(registers.Location(ctx.getID(), 1, 1))
- class DoneSetM(registers.DoneSet):
- def doneGet(self, token, error):
- pending.remove(token)
- if error:
- protocol.log("Error from Registers.setm", error)
- if not pending:
- onDone()
- pending.append(regs.setm(locs, (255, 255), DoneSetM()))
- if not pending:
- onDone()
- if ctx_ids:
- for ctx_id in ctx_ids:
- pending.append(regs.getContext(ctx_id, DoneGetContext()))
- pending.append(regs.getChildren(ctx_id, DoneGetChildren()))
- with lock:
- for ctx_id in _suspended:
- protocol.invokeLater(regTest, ctx_id)
- lock.wait(5)
-
-def testExpressions(c):
- if not _suspended: return
- from tcf.services import expressions
- ctl = sync.CommandControl(c)
- exprs = ctl.Expressions
- e = exprs.create(_suspended[0], None, "1+2*(3-4/2)").getE()
- id = e.get(expressions.PROP_ID)
- val, cls = exprs.evaluate(id).getE()
- print e.get(expressions.PROP_EXPRESSION), "=", val
- exprs.dispose(id)
-
-def testLineNumbers(c):
- if not _suspended: return
- from tcf.services import stacktrace
- ctl = sync.CommandControl(c)
- stack = ctl.StackTrace
- lineNumbers = ctl.LineNumbers
- for ctx_id in _suspended:
- bt = stack.getChildren(ctx_id).get()
- if bt:
- bt = stack.getContext(bt).get()
- for frame in bt:
- addr = frame.get(stacktrace.PROP_INSTRUCTION_ADDRESS)
- area = lineNumbers.mapToSource(ctx_id, addr, addr+1).get()
- print "Frame %d - CodeArea: %s" % (frame.get(stacktrace.PROP_LEVEL), area)
-
-def testSyncCommands(c):
- # simplified command execution
- ctl = sync.CommandControl(c)
- try:
- diag = ctl.Diagnostics
- except AttributeError:
- # no Diagnostics service
- return
- s = "Hello TCF World"
- r = diag.echo(s).getE()
- assert s == r
- pi = 3.141592654
- r = diag.echoFP(pi).getE()
- assert pi == r
- e = errors.ErrorReport("Test", errors.TCF_ERROR_OTHER)
- r = diag.echoERR(e.getAttributes()).getE()
- assert e.getAttributes() == r
- print "Diagnostic tests:", diag.getTestList().getE()
-
- for ctx_id in _suspended:
- print "Symbols:", ctl.Symbols.list(ctx_id)
- for ctx_id in _suspended:
- frame_ids = ctl.StackTrace.getChildren(ctx_id).get()
- if frame_ids:
- error, args = ctl.StackTrace.getContext(frame_ids)
- if not error: print "Stack contexts:", args
- def gotBreakpoints(error, bps):
- print "Got breakpoint list:", bps
- ctl.Breakpoints.getIDs(onDone=gotBreakpoints)
- try:
- print ctl.Processes.getChildren(None, False)
- except:
- pass # no Processes service
-
-def testTasks(c):
- if not _suspended: return
- from tcf.services import expressions
- from tcf.util import task
- def compute(expr, done=None):
- es = c.getRemoteService(expressions.NAME)
- if not es:
- done(Exception("No Expressions service"), None)
- return
- def doneCreate(token, error, ctx):
- if error:
- done(error, None)
- return
- def doneEval(token, error, val):
- done(error, val)
- es.evaluate(ctx.getID(), doneEval)
- es.create(_suspended[0], None, expr, doneCreate)
- t = task.Task(compute, "1+2*(3-4/2)", channel=c)
- val = t.get()
- print "Task result:", val
-
-def testEvents(c):
- from tcf.util import event
- recorder = event.EventRecorder(c)
- recorder.record("RunControl")
- ctl = sync.CommandControl(c)
- try:
- rc = ctl.RunControl
- except AttributeError:
- # no RunControl service
- return
- ctxs = rc.getChildren(None).get()
- if not ctxs: return
- ctx = ctxs[0]
- rc.resume(ctx, 0, 1, None).wait()
- print recorder
- rc.suspend(ctx).wait()
- print recorder
- recorder.stop()
-
-def testDataCache(c):
- from tcf.util import cache
- from tcf.services import runcontrol
- class ContextsCache(cache.DataCache):
- def startDataRetrieval(self):
- rc = self._channel.getRemoteService(runcontrol.NAME)
- if not rc:
- self.set(None, Exception("No RunControl service"), None)
- return
- cache = self
- pending = []
- contexts = []
- class DoneGetChildren(runcontrol.DoneGetChildren):
- def doneGetChildren(self, token, error, context_ids):
- pending.remove(token)
- if error:
- protocol.log("Error from RunControl.GetChildren", error)
- else:
- for c in context_ids:
- contexts.append(c)
- pending.append(rc.getChildren(c, self))
- if len(pending) == 0:
- cache.set(None, None, contexts)
- pending.append(rc.getChildren(None, DoneGetChildren()))
- contextsCache = ContextsCache(c)
- def done():
- print "ContextsCache is valid:", contextsCache.getData()
- protocol.invokeLater(contextsCache.validate, done)
-
-def testProcesses(c):
- from tcf.services import processes, processes_v1
- def processTest():
- proc = c.getRemoteService(processes_v1.NAME) or c.getRemoteService(processes.NAME)
- if not proc:
- return
- class DoneGetChildren(processes.DoneGetChildren):
- def doneGetChildren(self, token, error, context_ids):
- if error:
- protocol.log("Error from Processes.GetChildren", error)
- else:
- print "Processes:", context_ids
- proc.getChildren(None, False, DoneGetChildren())
- protocol.invokeLater(processTest)
-
-def testFileSystem(c):
- cmd = sync.CommandControl(c)
- try:
- fs = cmd.FileSystem
- except AttributeError:
- # no FileSystem service
- return
- roots = fs.roots().get()
- print "FileSystem roots:", roots
- user = fs.user().get()
- print "User info: ", user
-
-def testMemory(c):
- lock = threading.Condition()
- from tcf.services import memory
- def getContexts():
- mem = c.getRemoteService(memory.NAME)
- pending = []
- class DoneGetContext(memory.DoneGetContext):
- def doneGetContext(self, token, error, context):
- pending.remove(token)
- if error:
- protocol.log("Error from Memory.getContext", error)
- else:
- print context
- if len(pending) == 0:
- with lock:
- lock.notify()
- class DoneGetChildren(memory.DoneGetChildren):
- def doneGetChildren(self, token, error, context_ids):
- pending.remove(token)
- if error:
- protocol.log("Error from Memory.GetChildren", error)
- else:
- for c in context_ids:
- _memory.append(c)
- pending.append(mem.getContext(c, DoneGetContext()))
- pending.append(mem.getChildren(c, self))
- if len(pending) == 0:
- with lock:
- lock.notify()
- pending.append(mem.getChildren(None, DoneGetChildren()))
- with lock:
- protocol.invokeLater(getContexts)
- lock.wait(5)
-
-def testMemoryMap(c):
- if not _memory: return
- cmd = sync.CommandControl(c)
- try:
- mm = cmd.MemoryMap
- except AttributeError:
- # no MemoryMap service
- return
- id = _memory[0]
- lock = threading.Condition()
- from tcf.services import memorymap
- def getMap():
- mm = c.getRemoteService(memorymap.NAME)
- class DoneGet(memorymap.DoneGet):
- def doneGet(self, token, error, map):
- if error:
- protocol.log("Error from MemoryMap.get", error)
- else:
- print map
- with lock:
- lock.notify()
- mm.get(id, DoneGet())
- with lock:
- protocol.invokeLater(getMap)
- lock.wait(1)
- def setMap():
- mm = c.getRemoteService(memorymap.NAME)
- class DoneSet(memorymap.DoneSet):
- def doneSet(self, token, error):
- if error:
- protocol.log("Error from MemoryMap.set", error)
- with lock:
- lock.notify()
- mm.set(id, {memorymap.PROP_FILE_NAME : "/tmp/system.elf"}, DoneSet())
- with lock:
- protocol.invokeLater(setMap)
- lock.wait(1)
- map = mm.get(id).get()
- print "Memory map:", map
-
-def testPathMap(c):
- cmd = sync.CommandControl(c)
- try:
- pm = cmd.PathMap
- except AttributeError:
- # no PathMap service
- return
- lock = threading.Condition()
- from tcf.services import pathmap
- def getMap():
- pm = c.getRemoteService(pathmap.NAME)
- class DoneGet(pathmap.DoneGet):
- def doneGet(self, token, error, map):
- if error:
- protocol.log("Error from PathMap.get", error)
- else:
- print map
- with lock:
- lock.notify()
- pm.get(DoneGet())
- with lock:
- protocol.invokeLater(getMap)
- lock.wait(1)
- def setMap():
- pm = c.getRemoteService(pathmap.NAME)
- class DoneSet(pathmap.DoneSet):
- def doneSet(self, token, error):
- if error:
- protocol.log("Error from PathMap.set", error)
- with lock:
- lock.notify()
- pm.set({pathmap.PROP_SOURCE : "/tmp",
- pathmap.PROP_DESTINATION : "/home"}, DoneSet())
- with lock:
- protocol.invokeLater(setMap)
- lock.wait(1)
- map = pm.get().get()
- print "Path map:", map
-
-def testSysMonitor(c):
- cmd = sync.CommandControl(c)
- try:
- sm = cmd.SysMonitor
- except AttributeError:
- # no SysMonotor service
- return
- lock = threading.Condition()
- from tcf.services import sysmonitor
- processes = []
- def getProcesses():
- sm = c.getRemoteService(sysmonitor.NAME)
- pending = []
- class DoneGetChildren(sysmonitor.DoneGetChildren):
- def doneGetChildren(self, token, error, context_ids):
- pending.remove(token)
- if error:
- protocol.log("Error from SysMonitor.getChildren", error)
- else:
- class DoneGetContext(sysmonitor.DoneGetContext):
- def doneGetContext(self, token, error, context):
- pending.remove(token)
- if error:
- protocol.log("Error from SysMonitor.getContext", error)
- else:
- processes.append(context)
- if not pending:
- with lock:
- lock.notify()
- for id in context_ids:
- pending.append(sm.getContext(id, DoneGetContext()))
- if not pending:
- with lock:
- lock.notify()
- pending.append(sm.getChildren(None, DoneGetChildren()))
- with lock:
- protocol.invokeLater(getProcesses)
- lock.wait(5)
- print "%d processes found:" % len(processes)
- for p in processes:
- print p
- cmdl = sm.getCommandLine(p.getID()).get()
- if cmdl: print "Command line: ", cmdl
- envp = sm.getEnvironment(p.getID()).get()
- print "Environment: ", envp
-
-if __name__ == '__main__':
- test()
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import sys, time, threading, atexit
+import tcf
+from tcf import protocol, channel, errors
+from tcf.util import sync
+
+__TRACE = False
+class TraceListener(channel.TraceListener):
+ def onMessageReceived(self, type, token, service, name, data):
+ print "<<<", type, token, service, name, data
+ def onMessageSent(self, type, token, service, name, data):
+ print ">>>", type, token, service, name, data
+ def onChannelClosed(self, error):
+ print>>sys.stderr, "*** closed ***", error
+
+_suspended = []
+_memory = []
+
+def test():
+ protocol.startEventQueue()
+ atexit.register(protocol.getEventQueue().shutdown)
+ #testTimer()
+ try:
+ c = tcf.connect("TCP:127.0.0.1:1534")
+ except Exception as e:
+ protocol.log(e)
+ sys.exit()
+ assert c.state == channel.STATE_OPEN
+ if __TRACE: protocol.invokeLater(c.addTraceListener, TraceListener())
+ def printServices():
+ print "services=", c.getRemoteServices()
+ protocol.invokeLater(printServices)
+
+ try:
+ testRunControl(c)
+ testStackTrace(c)
+ testDisassembly(c)
+ testBreakpoints(c)
+ testSymbols(c)
+ testRegisters(c)
+ testExpressions(c)
+ testLineNumbers(c)
+ testSyncCommands(c)
+ testTasks(c)
+ testEvents(c)
+ testDataCache(c)
+ testProcesses(c)
+ testFileSystem(c)
+ testMemory(c)
+ testMemoryMap(c)
+ testPathMap(c)
+ testSysMonitor(c)
+ except Exception as e:
+ protocol.log(e)
+
+ if c.state == channel.STATE_OPEN:
+ time.sleep(5)
+ protocol.invokeLater(c.close)
+ time.sleep(2)
+
+
+def testTimer():
+ cond = threading.Condition()
+ def countdown(left):
+ if left == 0:
+ print "Ignition sequence started!"
+ with cond:
+ cond.notify()
+ return
+ print "%d seconds to go" % left
+ sys.stdout.flush()
+ protocol.invokeLaterWithDelay(1000, countdown, left - 1)
+ with cond:
+ protocol.invokeLaterWithDelay(0, countdown, 10)
+ cond.wait(15)
+
+def testRunControl(c):
+ lock = threading.Condition()
+ from tcf.services import runcontrol
+ def getContexts():
+ rctrl = c.getRemoteService(runcontrol.NAME)
+ pending = []
+ class DoneGetContext(runcontrol.DoneGetContext):
+ def doneGetContext(self, token, error, context):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from RunControl.getContext", error)
+ else:
+ print context
+ class DoneGetState(runcontrol.DoneGetState):
+ def doneGetState(self, token, error, suspended, pc, reason, params):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from RunControl.getState", error)
+ else:
+ print "suspended: ", suspended
+ print "pc: ", pc
+ print "reason: ", reason
+ print "params: ", params
+ if suspended:
+ _suspended.append(context.getID())
+ if len(pending) == 0:
+ with lock:
+ lock.notify()
+ if context and context.hasState(): pending.append(context.getState(DoneGetState()))
+ if len(pending) == 0:
+ with lock:
+ lock.notify()
+ class DoneGetChildren(runcontrol.DoneGetChildren):
+ def doneGetChildren(self, token, error, context_ids):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from RunControl.GetChildren", error)
+ else:
+ for c in context_ids:
+ pending.append(rctrl.getContext(c, DoneGetContext()))
+ pending.append(rctrl.getChildren(c, self))
+ if len(pending) == 0:
+ with lock:
+ lock.notify()
+ pending.append(rctrl.getChildren(None, DoneGetChildren()))
+ with lock:
+ protocol.invokeLater(getContexts)
+ lock.wait(5)
+ def listenerTest():
+ rc = c.getRemoteService(runcontrol.NAME)
+ class RCListener(runcontrol.RunControlListener):
+ def contextSuspended(self, *args):
+ print "context suspended: ", args
+ rc.removeListener(self)
+ def contextResumed(self, *args):
+ print "context resumed: ", args
+ def containerSuspended(self, *args):
+ print "container suspended:", args
+ rc.removeListener(self)
+ def containerResumed(self, *args):
+ print "container resumed:", args
+ rc.addListener(RCListener())
+ class DoneGetContext(runcontrol.DoneGetContext):
+ def doneGetContext(self, token, error, context):
+ if error:
+ protocol.log("Error from RunControl.getContext", error)
+ with lock: lock.notify()
+ return
+ class DoneResume(runcontrol.DoneCommand):
+ def doneCommand(self, token, error):
+ if error:
+ protocol.log("Error from RunControl.resume", error)
+ else:
+ context.suspend(runcontrol.DoneCommand())
+ with lock: lock.notify()
+ context.resume(runcontrol.RM_RESUME, 1, None, DoneResume())
+ rc.getContext(_suspended[0], DoneGetContext())
+
+ if _suspended:
+ with lock:
+ protocol.invokeLater(listenerTest)
+ lock.wait(5)
+
+def testBreakpoints(c):
+ from tcf.services import breakpoints
+ def testBPQuery():
+ bps = c.getRemoteService(breakpoints.NAME)
+ def doneGetIDs(token, error, ids):
+ if error:
+ protocol.log("Error from Breakpoints.getIDs", error)
+ return
+ print "Breakpoints :", ids
+ def doneGetProperties(token, error, props):
+ if error:
+ protocol.log("Error from Breakpoints.getProperties", error)
+ return
+ print "Breakpoint Properties: ", props
+ def doneGetStatus(token, error, props):
+ if error:
+ protocol.log("Error from Breakpoints.getStatus", error)
+ return
+ print "Breakpoint Status: ", props
+ for id in ids:
+ bps.getProperties(id, doneGetProperties)
+ bps.getStatus(id, doneGetStatus)
+ bps.getIDs(doneGetIDs)
+ protocol.invokeLater(testBPQuery)
+ def testBPSet():
+ bpsvc = c.getRemoteService(breakpoints.NAME)
+ class BPListener(breakpoints.BreakpointsListener):
+ def breakpointStatusChanged(self, id, status):
+ print "breakpointStatusChanged", id, status
+ def contextAdded(self, bps):
+ print "breakpointAdded", bps
+ bpsvc.removeListener(self)
+ def contextChanged(self, bps):
+ print "breakpointChanged", bps
+ def contextRemoved(self, ids):
+ print "breakpointRemoved", ids
+ bpsvc.addListener(BPListener())
+ def doneSet(token, error):
+ if error:
+ protocol.log("Error from Breakpoints.set", error)
+ return
+ bp = {
+ breakpoints.PROP_ID : "python:1",
+ breakpoints.PROP_ENABLED : True,
+ breakpoints.PROP_LOCATION : "sysClkRateGet"
+ }
+ bpsvc.set([bp], doneSet)
+ protocol.invokeLater(testBPSet)
+
+def testStackTrace(c):
+ from tcf.services import stacktrace
+ def stackTest(ctx_id):
+ stack = c.getRemoteService(stacktrace.NAME)
+ class DoneGetChildren(stacktrace.DoneGetChildren):
+ def doneGetChildren(self, token, error, ctx_ids):
+ if error:
+ protocol.log("Error from StackTrace.getChildren", error)
+ return
+ class DoneGetContext(stacktrace.DoneGetContext):
+ def doneGetContext(self, token, error, ctxs):
+ if error:
+ protocol.log("Error from StackTrace.getContext", error)
+ return
+ if ctxs:
+ for ctx in ctxs:
+ print ctx
+ stack.getContext(ctx_ids, DoneGetContext())
+ stack.getChildren(ctx_id, DoneGetChildren())
+ for ctx_id in _suspended:
+ protocol.invokeLater(stackTest, ctx_id)
+
+def testDisassembly(c):
+ if not _suspended: return
+ ctl = sync.CommandControl(c)
+ try:
+ dis = ctl.Disassembly
+ except AttributeError:
+ # no Disassembly service
+ return
+ for ctx_id in _suspended:
+ frames = ctl.StackTrace.getChildren(ctx_id).get()
+ if frames:
+ frameData = ctl.StackTrace.getContext(frames).get()
+ if frameData:
+ addr = frameData[0].get("IP")
+ if addr:
+ print "Disassemble context %s from 0x%x" % (ctx_id, addr)
+ lines = dis.disassemble(ctx_id, addr, 256, None).get()
+ if lines:
+ for line in lines:
+ print line
+
+def testSymbols(c):
+ from tcf.services import symbols
+ def symTest(ctx_id):
+ syms = c.getRemoteService(symbols.NAME)
+ class DoneList(symbols.DoneList):
+ def doneList(self, token, error, ctx_ids):
+ if error:
+ protocol.log("Error from Symbols.list", error)
+ return
+ class DoneGetContext(symbols.DoneGetContext):
+ def doneGetContext(self, token, error, ctx):
+ if error:
+ protocol.log("Error from Symbols.getContext", error)
+ return
+ print ctx
+ if ctx_ids:
+ for ctx_id in ctx_ids:
+ syms.getContext(ctx_id, DoneGetContext())
+ syms.list(ctx_id, DoneList())
+ for ctx_id in _suspended:
+ protocol.invokeLater(symTest, ctx_id)
+
+def testRegisters(c):
+ if not _suspended: return
+ from tcf.services import registers
+ lock = threading.Condition()
+ def regTest(ctx_id):
+ regs = c.getRemoteService(registers.NAME)
+ pending = []
+ def onDone():
+ with lock: lock.notify()
+ class DoneGetChildren(registers.DoneGetChildren):
+ def doneGetChildren(self, token, error, ctx_ids):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Registers.getChildren", error)
+ if not pending:
+ onDone()
+ class DoneGetContext(registers.DoneGetContext):
+ def doneGetContext(self, token, error, ctx):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Registers.getContext", error)
+ else:
+ print ctx
+ if ctx.isReadable() and not ctx.isReadOnce() and ctx.getSize() >= 2:
+ locs = []
+ locs.append(registers.Location(ctx.getID(), 0, 1))
+ locs.append(registers.Location(ctx.getID(), 1, 1))
+ class DoneGetM(registers.DoneGet):
+ def doneGet(self, token, error, value):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Registers.getm", error)
+ else:
+ print "getm", ctx.getID(), map(ord, value)
+ if not pending:
+ onDone()
+ pending.append(regs.getm(locs, DoneGetM()))
+ if ctx.isWriteable() and not ctx.isWriteOnce() and ctx.getSize() >= 2:
+ locs = []
+ locs.append(registers.Location(ctx.getID(), 0, 1))
+ locs.append(registers.Location(ctx.getID(), 1, 1))
+ class DoneSetM(registers.DoneSet):
+ def doneGet(self, token, error):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Registers.setm", error)
+ if not pending:
+ onDone()
+ pending.append(regs.setm(locs, (255, 255), DoneSetM()))
+ if not pending:
+ onDone()
+ if ctx_ids:
+ for ctx_id in ctx_ids:
+ pending.append(regs.getContext(ctx_id, DoneGetContext()))
+ pending.append(regs.getChildren(ctx_id, DoneGetChildren()))
+ with lock:
+ for ctx_id in _suspended:
+ protocol.invokeLater(regTest, ctx_id)
+ lock.wait(5)
+
+def testExpressions(c):
+ if not _suspended: return
+ from tcf.services import expressions
+ ctl = sync.CommandControl(c)
+ exprs = ctl.Expressions
+ e = exprs.create(_suspended[0], None, "1+2*(3-4/2)").getE()
+ id = e.get(expressions.PROP_ID)
+ val, cls = exprs.evaluate(id).getE()
+ print e.get(expressions.PROP_EXPRESSION), "=", val
+ exprs.dispose(id)
+
+def testLineNumbers(c):
+ if not _suspended: return
+ from tcf.services import stacktrace
+ ctl = sync.CommandControl(c)
+ stack = ctl.StackTrace
+ lineNumbers = ctl.LineNumbers
+ for ctx_id in _suspended:
+ bt = stack.getChildren(ctx_id).get()
+ if bt:
+ bt = stack.getContext(bt).get()
+ for frame in bt:
+ addr = frame.get(stacktrace.PROP_INSTRUCTION_ADDRESS)
+ area = lineNumbers.mapToSource(ctx_id, addr, addr+1).get()
+ print "Frame %d - CodeArea: %s" % (frame.get(stacktrace.PROP_LEVEL), area)
+
+def testSyncCommands(c):
+ # simplified command execution
+ ctl = sync.CommandControl(c)
+ try:
+ diag = ctl.Diagnostics
+ except AttributeError:
+ # no Diagnostics service
+ return
+ s = "Hello TCF World"
+ r = diag.echo(s).getE()
+ assert s == r
+ pi = 3.141592654
+ r = diag.echoFP(pi).getE()
+ assert pi == r
+ e = errors.ErrorReport("Test", errors.TCF_ERROR_OTHER)
+ r = diag.echoERR(e.getAttributes()).getE()
+ assert e.getAttributes() == r
+ print "Diagnostic tests:", diag.getTestList().getE()
+
+ for ctx_id in _suspended:
+ print "Symbols:", ctl.Symbols.list(ctx_id)
+ for ctx_id in _suspended:
+ frame_ids = ctl.StackTrace.getChildren(ctx_id).get()
+ if frame_ids:
+ error, args = ctl.StackTrace.getContext(frame_ids)
+ if not error: print "Stack contexts:", args
+ def gotBreakpoints(error, bps):
+ print "Got breakpoint list:", bps
+ ctl.Breakpoints.getIDs(onDone=gotBreakpoints)
+ try:
+ print ctl.Processes.getChildren(None, False)
+ except:
+ pass # no Processes service
+
+def testTasks(c):
+ if not _suspended: return
+ from tcf.services import expressions
+ from tcf.util import task
+ def compute(expr, done=None):
+ es = c.getRemoteService(expressions.NAME)
+ if not es:
+ done(Exception("No Expressions service"), None)
+ return
+ def doneCreate(token, error, ctx):
+ if error:
+ done(error, None)
+ return
+ def doneEval(token, error, val):
+ done(error, val)
+ es.evaluate(ctx.getID(), doneEval)
+ es.create(_suspended[0], None, expr, doneCreate)
+ t = task.Task(compute, "1+2*(3-4/2)", channel=c)
+ val = t.get()
+ print "Task result:", val
+
+def testEvents(c):
+ from tcf.util import event
+ recorder = event.EventRecorder(c)
+ recorder.record("RunControl")
+ ctl = sync.CommandControl(c)
+ try:
+ rc = ctl.RunControl
+ except AttributeError:
+ # no RunControl service
+ return
+ ctxs = rc.getChildren(None).get()
+ if not ctxs: return
+ ctx = ctxs[0]
+ rc.resume(ctx, 0, 1, None).wait()
+ print recorder
+ rc.suspend(ctx).wait()
+ print recorder
+ recorder.stop()
+
+def testDataCache(c):
+ from tcf.util import cache
+ from tcf.services import runcontrol
+ class ContextsCache(cache.DataCache):
+ def startDataRetrieval(self):
+ rc = self._channel.getRemoteService(runcontrol.NAME)
+ if not rc:
+ self.set(None, Exception("No RunControl service"), None)
+ return
+ cache = self
+ pending = []
+ contexts = []
+ class DoneGetChildren(runcontrol.DoneGetChildren):
+ def doneGetChildren(self, token, error, context_ids):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from RunControl.GetChildren", error)
+ else:
+ for c in context_ids:
+ contexts.append(c)
+ pending.append(rc.getChildren(c, self))
+ if len(pending) == 0:
+ cache.set(None, None, contexts)
+ pending.append(rc.getChildren(None, DoneGetChildren()))
+ contextsCache = ContextsCache(c)
+ def done():
+ print "ContextsCache is valid:", contextsCache.getData()
+ protocol.invokeLater(contextsCache.validate, done)
+
+def testProcesses(c):
+ from tcf.services import processes, processes_v1
+ def processTest():
+ proc = c.getRemoteService(processes_v1.NAME) or c.getRemoteService(processes.NAME)
+ if not proc:
+ return
+ class DoneGetChildren(processes.DoneGetChildren):
+ def doneGetChildren(self, token, error, context_ids):
+ if error:
+ protocol.log("Error from Processes.GetChildren", error)
+ else:
+ print "Processes:", context_ids
+ proc.getChildren(None, False, DoneGetChildren())
+ protocol.invokeLater(processTest)
+
+def testFileSystem(c):
+ cmd = sync.CommandControl(c)
+ try:
+ fs = cmd.FileSystem
+ except AttributeError:
+ # no FileSystem service
+ return
+ roots = fs.roots().get()
+ print "FileSystem roots:", roots
+ user = fs.user().get()
+ print "User info: ", user
+
+def testMemory(c):
+ lock = threading.Condition()
+ from tcf.services import memory
+ def getContexts():
+ mem = c.getRemoteService(memory.NAME)
+ pending = []
+ class DoneGetContext(memory.DoneGetContext):
+ def doneGetContext(self, token, error, context):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Memory.getContext", error)
+ else:
+ print context
+ if len(pending) == 0:
+ with lock:
+ lock.notify()
+ class DoneGetChildren(memory.DoneGetChildren):
+ def doneGetChildren(self, token, error, context_ids):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from Memory.GetChildren", error)
+ else:
+ for c in context_ids:
+ _memory.append(c)
+ pending.append(mem.getContext(c, DoneGetContext()))
+ pending.append(mem.getChildren(c, self))
+ if len(pending) == 0:
+ with lock:
+ lock.notify()
+ pending.append(mem.getChildren(None, DoneGetChildren()))
+ with lock:
+ protocol.invokeLater(getContexts)
+ lock.wait(5)
+
+def testMemoryMap(c):
+ if not _memory: return
+ cmd = sync.CommandControl(c)
+ try:
+ mm = cmd.MemoryMap
+ except AttributeError:
+ # no MemoryMap service
+ return
+ id = _memory[0]
+ lock = threading.Condition()
+ from tcf.services import memorymap
+ def getMap():
+ mm = c.getRemoteService(memorymap.NAME)
+ class DoneGet(memorymap.DoneGet):
+ def doneGet(self, token, error, map):
+ if error:
+ protocol.log("Error from MemoryMap.get", error)
+ else:
+ print map
+ with lock:
+ lock.notify()
+ mm.get(id, DoneGet())
+ with lock:
+ protocol.invokeLater(getMap)
+ lock.wait(1)
+ def setMap():
+ mm = c.getRemoteService(memorymap.NAME)
+ class DoneSet(memorymap.DoneSet):
+ def doneSet(self, token, error):
+ if error:
+ protocol.log("Error from MemoryMap.set", error)
+ with lock:
+ lock.notify()
+ mm.set(id, {memorymap.PROP_FILE_NAME : "/tmp/system.elf"}, DoneSet())
+ with lock:
+ protocol.invokeLater(setMap)
+ lock.wait(1)
+ map = mm.get(id).get()
+ print "Memory map:", map
+
+def testPathMap(c):
+ cmd = sync.CommandControl(c)
+ try:
+ pm = cmd.PathMap
+ except AttributeError:
+ # no PathMap service
+ return
+ lock = threading.Condition()
+ from tcf.services import pathmap
+ def getMap():
+ pm = c.getRemoteService(pathmap.NAME)
+ class DoneGet(pathmap.DoneGet):
+ def doneGet(self, token, error, map):
+ if error:
+ protocol.log("Error from PathMap.get", error)
+ else:
+ print map
+ with lock:
+ lock.notify()
+ pm.get(DoneGet())
+ with lock:
+ protocol.invokeLater(getMap)
+ lock.wait(1)
+ def setMap():
+ pm = c.getRemoteService(pathmap.NAME)
+ class DoneSet(pathmap.DoneSet):
+ def doneSet(self, token, error):
+ if error:
+ protocol.log("Error from PathMap.set", error)
+ with lock:
+ lock.notify()
+ pm.set({pathmap.PROP_SOURCE : "/tmp",
+ pathmap.PROP_DESTINATION : "/home"}, DoneSet())
+ with lock:
+ protocol.invokeLater(setMap)
+ lock.wait(1)
+ map = pm.get().get()
+ print "Path map:", map
+
+def testSysMonitor(c):
+ cmd = sync.CommandControl(c)
+ try:
+ sm = cmd.SysMonitor
+ except AttributeError:
+ # no SysMonotor service
+ return
+ lock = threading.Condition()
+ from tcf.services import sysmonitor
+ processes = []
+ def getProcesses():
+ sm = c.getRemoteService(sysmonitor.NAME)
+ pending = []
+ class DoneGetChildren(sysmonitor.DoneGetChildren):
+ def doneGetChildren(self, token, error, context_ids):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from SysMonitor.getChildren", error)
+ else:
+ class DoneGetContext(sysmonitor.DoneGetContext):
+ def doneGetContext(self, token, error, context):
+ pending.remove(token)
+ if error:
+ protocol.log("Error from SysMonitor.getContext", error)
+ else:
+ processes.append(context)
+ if not pending:
+ with lock:
+ lock.notify()
+ for id in context_ids:
+ pending.append(sm.getContext(id, DoneGetContext()))
+ if not pending:
+ with lock:
+ lock.notify()
+ pending.append(sm.getChildren(None, DoneGetChildren()))
+ with lock:
+ protocol.invokeLater(getProcesses)
+ lock.wait(5)
+ print "%d processes found:" % len(processes)
+ for p in processes:
+ print p
+ cmdl = sm.getCommandLine(p.getID()).get()
+ if cmdl: print "Command line: ", cmdl
+ envp = sm.getEnvironment(p.getID()).get()
+ print "Environment: ", envp
+
+if __name__ == '__main__':
+ test()
diff --git a/python/src/tcf/transport.py b/python/src/tcf/transport.py
index 295f1c857..b22b2f9f0 100644
--- a/python/src/tcf/transport.py
+++ b/python/src/tcf/transport.py
@@ -1,158 +1,158 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import threading
-import protocol, channel
-from tcf.services import locator
-
-_channels = []
-_listeners = []
-_transports = {}
-_lock = threading.RLock()
-
-class TransportProvider(object):
- """
- TransportProvider represents communication protocol that can be used to open TCF communication channels.
- Examples of transports are: TCP/IP, RS-232, USB.
-
- Client can implement this interface if they want to provide support for a transport that is not
- supported directly by the framework.
- """
-
- def getName(self):
- """
- Return transport name. Same as used as peer attribute, @see IPeer.ATTR_TRANSPORT_NAME
- @return transport name.
- """
- raise NotImplementedError("Abstract method")
-
- def openChannel(self, peer):
- """
- Open channel to communicate with this peer using this transport.
- Note: the channel can be not fully open yet when this method returns.
- It's state can be IChannel.STATE_OPENING.
- Protocol.Listener will be called when the channel will be opened or closed.
- @param peer - a IPeer object that describes remote end-point of the channel.
- @return TCF communication channel.
- """
- raise NotImplementedError("Abstract method")
-
-def addTransportProvider(transport):
- name = transport.getName()
- assert name
- with _lock:
- if _transports.get(name): raise Exception("Already registered: " + name)
- _transports[name] = transport
-
-def removeTransportProvider(transport):
- name = transport.getName()
- assert name
- with _lock:
- if _transports.get(name) == transport: del _transports[name]
-
-def openChannel(peer):
- name = peer.getTransportName()
- if not name: raise Exception("No transport name")
- with _lock:
- provider = _transports.get(name)
- if not provider: raise Exception("Unknown transport name: " + name)
- return provider.openChannel(peer)
-
-def channelOpened(channel):
- assert channel not in _channels
- _channels.append(channel)
- for l in _listeners:
- try:
- l.onChannelOpen(channel)
- except Exception as x:
- protocol.log("Exception in channel listener", x)
-
-def channelClosed(channel, error):
- assert channel in _channels
- _channels.remove(channel)
-
-def getOpenChannels():
- return _channels[:]
-
-def addChannelOpenListener(listener):
- assert listener
- _listeners.append(listener)
-
-def removeChannelOpenListener(listener):
- try:
- _listeners.remove(listener)
- except ValueError:
- pass # ignore
-
-class TCPTransportProvider(TransportProvider):
- def getName(self):
- return "TCP"
- def openChannel(self, p):
- assert self.getName() == p.getTransportName()
- from tcf import peer
- attrs = p.getAttributes()
- host = attrs.get(peer.ATTR_IP_HOST)
- port = attrs.get(peer.ATTR_IP_PORT)
- if not host: raise RuntimeError("No host name")
- from channel.ChannelTCP import ChannelTCP
- return ChannelTCP(p, host, _parsePort(port))
-
-def _parsePort(port):
- if not port: raise Exception("No port number")
- try:
- return int(port)
- except Exception:
- raise RuntimeError(
- "Invalid value of \"Port\" attribute. Must be decimal number.")
-
-def sendEvent(service_name, event_name, data):
- """
- Transmit TCF event message.
- The message is sent to all open communication channels - broadcasted.
-
- This is internal API, TCF clients should use protocol.sendEvent().
- """
- for c in _channels:
- # Skip channels that are executing "redirect" command - STATE_OPENING
- if c.getState() == channel.STATE_OPEN:
- s = c.getLocalService(service_name)
- if s: c.sendEvent(s, event_name, data)
-
-def sync(done):
- """
- Call back after TCF messages sent by this host up to this moment are delivered
- to their intended targets. This method is intended for synchronization of messages
- across multiple channels.
-
- Note: Cross channel synchronization can reduce performance and throughput.
- Most clients don't need cross channel synchronization and should not call this method.
-
- @param done will be executed by dispatch thread after communication
- messages are delivered to corresponding targets.
-
- This is internal API, TCF clients should use protocol.sync().
- """
- set = set()
- class DoneSync(locator.DoneSync):
- def doneSync(self, token):
- assert set.contains(token)
- set.remove(token)
- if len(set) == 0: done()
- done_sync = DoneSync()
- for c in _channels:
- if c.getState() == channel.STATE_OPEN:
- s = c.getRemoteService(locator.NAME)
- if s: set.append(s.sync(done_sync))
- if len(set) == 0: protocol.invokeLater(done)
-
-# initialize TCP transport
-addTransportProvider(TCPTransportProvider())
-
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading
+import protocol, channel
+from tcf.services import locator
+
+_channels = []
+_listeners = []
+_transports = {}
+_lock = threading.RLock()
+
+class TransportProvider(object):
+ """
+ TransportProvider represents communication protocol that can be used to open TCF communication channels.
+ Examples of transports are: TCP/IP, RS-232, USB.
+
+ Client can implement this interface if they want to provide support for a transport that is not
+ supported directly by the framework.
+ """
+
+ def getName(self):
+ """
+ Return transport name. Same as used as peer attribute, @see IPeer.ATTR_TRANSPORT_NAME
+ @return transport name.
+ """
+ raise NotImplementedError("Abstract method")
+
+ def openChannel(self, peer):
+ """
+ Open channel to communicate with this peer using this transport.
+ Note: the channel can be not fully open yet when this method returns.
+ It's state can be IChannel.STATE_OPENING.
+ Protocol.Listener will be called when the channel will be opened or closed.
+ @param peer - a IPeer object that describes remote end-point of the channel.
+ @return TCF communication channel.
+ """
+ raise NotImplementedError("Abstract method")
+
+def addTransportProvider(transport):
+ name = transport.getName()
+ assert name
+ with _lock:
+ if _transports.get(name): raise Exception("Already registered: " + name)
+ _transports[name] = transport
+
+def removeTransportProvider(transport):
+ name = transport.getName()
+ assert name
+ with _lock:
+ if _transports.get(name) == transport: del _transports[name]
+
+def openChannel(peer):
+ name = peer.getTransportName()
+ if not name: raise Exception("No transport name")
+ with _lock:
+ provider = _transports.get(name)
+ if not provider: raise Exception("Unknown transport name: " + name)
+ return provider.openChannel(peer)
+
+def channelOpened(channel):
+ assert channel not in _channels
+ _channels.append(channel)
+ for l in _listeners:
+ try:
+ l.onChannelOpen(channel)
+ except Exception as x:
+ protocol.log("Exception in channel listener", x)
+
+def channelClosed(channel, error):
+ assert channel in _channels
+ _channels.remove(channel)
+
+def getOpenChannels():
+ return _channels[:]
+
+def addChannelOpenListener(listener):
+ assert listener
+ _listeners.append(listener)
+
+def removeChannelOpenListener(listener):
+ try:
+ _listeners.remove(listener)
+ except ValueError:
+ pass # ignore
+
+class TCPTransportProvider(TransportProvider):
+ def getName(self):
+ return "TCP"
+ def openChannel(self, p):
+ assert self.getName() == p.getTransportName()
+ from tcf import peer
+ attrs = p.getAttributes()
+ host = attrs.get(peer.ATTR_IP_HOST)
+ port = attrs.get(peer.ATTR_IP_PORT)
+ if not host: raise RuntimeError("No host name")
+ from channel.ChannelTCP import ChannelTCP
+ return ChannelTCP(p, host, _parsePort(port))
+
+def _parsePort(port):
+ if not port: raise Exception("No port number")
+ try:
+ return int(port)
+ except Exception:
+ raise RuntimeError(
+ "Invalid value of \"Port\" attribute. Must be decimal number.")
+
+def sendEvent(service_name, event_name, data):
+ """
+ Transmit TCF event message.
+ The message is sent to all open communication channels - broadcasted.
+
+ This is internal API, TCF clients should use protocol.sendEvent().
+ """
+ for c in _channels:
+ # Skip channels that are executing "redirect" command - STATE_OPENING
+ if c.getState() == channel.STATE_OPEN:
+ s = c.getLocalService(service_name)
+ if s: c.sendEvent(s, event_name, data)
+
+def sync(done):
+ """
+ Call back after TCF messages sent by this host up to this moment are delivered
+ to their intended targets. This method is intended for synchronization of messages
+ across multiple channels.
+
+ Note: Cross channel synchronization can reduce performance and throughput.
+ Most clients don't need cross channel synchronization and should not call this method.
+
+ @param done will be executed by dispatch thread after communication
+ messages are delivered to corresponding targets.
+
+ This is internal API, TCF clients should use protocol.sync().
+ """
+ set = set()
+ class DoneSync(locator.DoneSync):
+ def doneSync(self, token):
+ assert set.contains(token)
+ set.remove(token)
+ if len(set) == 0: done()
+ done_sync = DoneSync()
+ for c in _channels:
+ if c.getState() == channel.STATE_OPEN:
+ s = c.getRemoteService(locator.NAME)
+ if s: set.append(s.sync(done_sync))
+ if len(set) == 0: protocol.invokeLater(done)
+
+# initialize TCP transport
+addTransportProvider(TCPTransportProvider())
+
diff --git a/python/src/tcf/util/__init__.py b/python/src/tcf/util/__init__.py
index cf36110a7..29aa42bc1 100644
--- a/python/src/tcf/util/__init__.py
+++ b/python/src/tcf/util/__init__.py
@@ -1,10 +1,10 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
diff --git a/python/src/tcf/util/cache.py b/python/src/tcf/util/cache.py
index aaa8622c3..7e33c535e 100644
--- a/python/src/tcf/util/cache.py
+++ b/python/src/tcf/util/cache.py
@@ -1,270 +1,270 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import cStringIO
-from tcf import protocol, channel
-
-class DataCache(object):
- """
- Objects of this class are used to cache TCF remote data.
- The cache is asynchronous state machine. The states are:
- 1. Valid - cache is in sync with remote data, use getError() and getData() to get cached data
- 2. Invalid - cache is out of sync, start data retrieval by calling validate()
- 3. Pending - cache is waiting result of a command that was sent to remote peer
- 4. Disposed - cache is disposed and cannot be used to store data.
-
- A cache instance can be created on any data type that needs to be cached.
- Examples might be context children list, context properties, context state, memory data,
- register data, symbol, variable, etc.
- Clients of cache items can register for cache changes, but don't need to think about any particular events
- since that is handled by the cache item itself.
-
- A typical cache client should implement Runnable interface.
- The implementation of run() method should:
-
- Validate all cache items required for client task.
- If anything is invalid then client should not alter any shared data structures,
- should discard any intermediate results and register (wait) for changes of invalid cache instance(s) state.
- When cache item state changes, client is invoked again and full validation is restarted.
- Once everything is valid, client completes its task in a single dispatch cycle.
-
- Note: clients should never retain copies of remote data across dispatch cycles!
- Such data would get out of sync and compromise data consistency.
- All remote data and everything derived from remote data should be kept in cache items
- that implement proper event handling and can keep data consistent across dispatch cycles.
- """
-
- __error = None
- __valid = None
- __posted = False
- __disposed = False
- __data = None
-
- def __init__(self, channel):
- assert channel
- self._channel = channel
- self._command = None
- self.__waiting_list = None
-
- def post(self):
- if self.__posted: return
- if not self.__waiting_list: return
- protocol.invokeLater(self)
- self.__posted = True
-
- def isValid(self):
- """
- @return True if cache contains up-to-date data or error.
- """
- return self.__valid
-
- def isPending(self):
- """
- @return True if data retrieval command is in progress.
- """
- return self._command is not None
-
- def isDisposed(self):
- """
- @return True if cache is disposed.
- """
- return self.__disposed
-
- def getError(self):
- """
- @return error object if data retrieval ended with an error, or None if retrieval was successful.
- Note: It is prohibited to call this method when cache is not valid.
- """
- assert self.__valid
- return self.__error
-
- def getData(self):
- """
- @return cached data object.
- Note: It is prohibited to call this method when cache is not valid.
- """
- assert protocol.isDispatchThread()
- assert self.__valid
- return self.__data
-
- def __call__(self):
- """
- Notify waiting clients about cache state change and remove them from wait list.
- It is responsibility of clients to check if the state change was one they are waiting for.
- Clients are not intended to call this method.
- """
- assert protocol.isDispatchThread()
- self.__posted = False
- if self.__waiting_list:
- arr = self.__waiting_list
- self.__waiting_list = None
- for r in arr:
- if isinstance(r, DataCache) and r._DataCache__posted: continue
- r()
- if self.__waiting_list is None: self.__waiting_list = arr
-
- def wait(self, cb):
- """
- Add a client call-back to cache wait list.
- Client call-backs are activated when cache state changes.
- Call-backs are removed from waiting list after that.
- It is responsibility of clients to check if the state change was one they are waiting for.
- @param cb - a call-back object
- """
- assert protocol.isDispatchThread()
- assert not self.__disposed
- assert not self.__valid
- if cb and not self.isWaiting(cb):
- if self.__waiting_list is None: self.__waiting_list = []
- self.__waiting_list.append(cb)
-
- def isWaiting(self, cb):
- """
- Return True if a client call-back is waiting for state changes of this cache item.
- @param cb - a call-back object.
- @return True if 'cb' is in the wait list.
- """
- if not self.__waiting_list: return False
- for r in self.__waiting_list:
- if r is cb: return True
- return False
-
- def __validate(self):
- """
- Initiate data retrieval if the cache is not valid.
- @return True if the cache is already valid
- """
- assert protocol.isDispatchThread()
- if self.__disposed or self._channel.getState() != channel.STATE_OPEN:
- self._command = None
- self.__valid = True
- self.__error = None
- self.__data = None
- else:
- if self._command is not None: return False
- if not self.__valid and not self.startDataRetrieval(): return False
- assert self.__valid
- assert self._command is None
- self.post()
- return True
-
- def validate(self, cb=None):
- """
- If the cache is not valid, initiate data retrieval and
- add a client call-back to cache wait list.
- Client call-backs are activated when cache state changes.
- Call-backs are removed from waiting list after that.
- It is responsibility of clients to check if the state change was one they are waiting for.
- If the cache is valid do nothing and return True.
- @param cb - a call-back object (optional)
- @return True if the cache is already valid
- """
- if not self.__validate():
- if cb: self.wait(cb)
- return False
- return True
-
- def start(self, command):
- """
- Start cache pending state.
- Pending state is when the cache is waiting for a TCF command to return results.
- @param command - TCF command handle.
- """
- assert not self.__valid
- assert command
- assert self._command is None
- self._command = command
-
- def done(self, command):
- """
- End cache pending state, but not mark the cache as valid.
- @param command - TCF command handle.
- """
- if self._command is not command: return
- assert not self.__valid
- self._command = None
- self.post()
-
- def set(self, token, error, data):
- """
- End cache pending state and mark the cache as valid.
- If 'token' != None, the data represent results from a completed command.
- The data should be ignored if current cache pending command is not same as 'token'.
- It can happen if the cache was reset or canceled during data retrieval.
- @param token - pending command handle or None.
- @param error - data retrieval error or None
- @param data - up-to-date data object
- """
- assert protocol.isDispatchThread()
- if token and self._command is not token: return
- self._command = None
- if not self.__disposed:
- assert not self.__valid
- if self._channel.getState() != channel.STATE_OPEN:
- self.__error = None
- self.__data = None
- self.__error = error
- self.__data = data
- self.__valid = True
- self.post()
-
- def reset(self, data=None):
- """
- Force cache to become valid, cancel pending data retrieval if data is provided.
- @param data - up-to-date data object (optional)
- """
- assert protocol.isDispatchThread()
- if data is not None and self._command is not None:
- self._command.cancel()
- self._command = None
- if not self.__disposed:
- self.__data = data
- self.__error = None
- self.__valid = True
- self.post()
-
- def cancel(self):
- """
- Invalidate the cache.
- Cancel pending data retrieval if any.
- """
- self.reset()
- if self._command is not None:
- self._command.cancel()
- self._command = None
-
- def dispose(self):
- """
- Dispose the cache.
- Cancel pending data retrieval if any.
- """
- self.cancel()
- self.__valid = True
- self.__disposed = True
-
- def __str__(self):
- bf = cStringIO.StringIO()
- bf.write('[')
- if self.__valid: bf.append("valid,")
- if self.__disposed: bf.write("disposed,")
- if self.__posted: bf.write("posted,")
- if self.__error is not None: bf.write("error,")
- bf.write("data=")
- bf.write(str(self.__data))
- bf.write(']')
- return bf.getvalue()
-
- def startDataRetrieval(self):
- """
- Sub-classes should override this method to implement actual data retrieval logic.
- @return True is all done, False if retrieval is in progress.
- """
- raise NotImplementedError("Abstract method")
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import cStringIO
+from tcf import protocol, channel
+
+class DataCache(object):
+ """
+ Objects of this class are used to cache TCF remote data.
+ The cache is asynchronous state machine. The states are:
+ 1. Valid - cache is in sync with remote data, use getError() and getData() to get cached data
+ 2. Invalid - cache is out of sync, start data retrieval by calling validate()
+ 3. Pending - cache is waiting result of a command that was sent to remote peer
+ 4. Disposed - cache is disposed and cannot be used to store data.
+
+ A cache instance can be created on any data type that needs to be cached.
+ Examples might be context children list, context properties, context state, memory data,
+ register data, symbol, variable, etc.
+ Clients of cache items can register for cache changes, but don't need to think about any particular events
+ since that is handled by the cache item itself.
+
+ A typical cache client should implement Runnable interface.
+ The implementation of run() method should:
+
+ Validate all cache items required for client task.
+ If anything is invalid then client should not alter any shared data structures,
+ should discard any intermediate results and register (wait) for changes of invalid cache instance(s) state.
+ When cache item state changes, client is invoked again and full validation is restarted.
+ Once everything is valid, client completes its task in a single dispatch cycle.
+
+ Note: clients should never retain copies of remote data across dispatch cycles!
+ Such data would get out of sync and compromise data consistency.
+ All remote data and everything derived from remote data should be kept in cache items
+ that implement proper event handling and can keep data consistent across dispatch cycles.
+ """
+
+ __error = None
+ __valid = None
+ __posted = False
+ __disposed = False
+ __data = None
+
+ def __init__(self, channel):
+ assert channel
+ self._channel = channel
+ self._command = None
+ self.__waiting_list = None
+
+ def post(self):
+ if self.__posted: return
+ if not self.__waiting_list: return
+ protocol.invokeLater(self)
+ self.__posted = True
+
+ def isValid(self):
+ """
+ @return True if cache contains up-to-date data or error.
+ """
+ return self.__valid
+
+ def isPending(self):
+ """
+ @return True if data retrieval command is in progress.
+ """
+ return self._command is not None
+
+ def isDisposed(self):
+ """
+ @return True if cache is disposed.
+ """
+ return self.__disposed
+
+ def getError(self):
+ """
+ @return error object if data retrieval ended with an error, or None if retrieval was successful.
+ Note: It is prohibited to call this method when cache is not valid.
+ """
+ assert self.__valid
+ return self.__error
+
+ def getData(self):
+ """
+ @return cached data object.
+ Note: It is prohibited to call this method when cache is not valid.
+ """
+ assert protocol.isDispatchThread()
+ assert self.__valid
+ return self.__data
+
+ def __call__(self):
+ """
+ Notify waiting clients about cache state change and remove them from wait list.
+ It is responsibility of clients to check if the state change was one they are waiting for.
+ Clients are not intended to call this method.
+ """
+ assert protocol.isDispatchThread()
+ self.__posted = False
+ if self.__waiting_list:
+ arr = self.__waiting_list
+ self.__waiting_list = None
+ for r in arr:
+ if isinstance(r, DataCache) and r._DataCache__posted: continue
+ r()
+ if self.__waiting_list is None: self.__waiting_list = arr
+
+ def wait(self, cb):
+ """
+ Add a client call-back to cache wait list.
+ Client call-backs are activated when cache state changes.
+ Call-backs are removed from waiting list after that.
+ It is responsibility of clients to check if the state change was one they are waiting for.
+ @param cb - a call-back object
+ """
+ assert protocol.isDispatchThread()
+ assert not self.__disposed
+ assert not self.__valid
+ if cb and not self.isWaiting(cb):
+ if self.__waiting_list is None: self.__waiting_list = []
+ self.__waiting_list.append(cb)
+
+ def isWaiting(self, cb):
+ """
+ Return True if a client call-back is waiting for state changes of this cache item.
+ @param cb - a call-back object.
+ @return True if 'cb' is in the wait list.
+ """
+ if not self.__waiting_list: return False
+ for r in self.__waiting_list:
+ if r is cb: return True
+ return False
+
+ def __validate(self):
+ """
+ Initiate data retrieval if the cache is not valid.
+ @return True if the cache is already valid
+ """
+ assert protocol.isDispatchThread()
+ if self.__disposed or self._channel.getState() != channel.STATE_OPEN:
+ self._command = None
+ self.__valid = True
+ self.__error = None
+ self.__data = None
+ else:
+ if self._command is not None: return False
+ if not self.__valid and not self.startDataRetrieval(): return False
+ assert self.__valid
+ assert self._command is None
+ self.post()
+ return True
+
+ def validate(self, cb=None):
+ """
+ If the cache is not valid, initiate data retrieval and
+ add a client call-back to cache wait list.
+ Client call-backs are activated when cache state changes.
+ Call-backs are removed from waiting list after that.
+ It is responsibility of clients to check if the state change was one they are waiting for.
+ If the cache is valid do nothing and return True.
+ @param cb - a call-back object (optional)
+ @return True if the cache is already valid
+ """
+ if not self.__validate():
+ if cb: self.wait(cb)
+ return False
+ return True
+
+ def start(self, command):
+ """
+ Start cache pending state.
+ Pending state is when the cache is waiting for a TCF command to return results.
+ @param command - TCF command handle.
+ """
+ assert not self.__valid
+ assert command
+ assert self._command is None
+ self._command = command
+
+ def done(self, command):
+ """
+ End cache pending state, but not mark the cache as valid.
+ @param command - TCF command handle.
+ """
+ if self._command is not command: return
+ assert not self.__valid
+ self._command = None
+ self.post()
+
+ def set(self, token, error, data):
+ """
+ End cache pending state and mark the cache as valid.
+ If 'token' != None, the data represent results from a completed command.
+ The data should be ignored if current cache pending command is not same as 'token'.
+ It can happen if the cache was reset or canceled during data retrieval.
+ @param token - pending command handle or None.
+ @param error - data retrieval error or None
+ @param data - up-to-date data object
+ """
+ assert protocol.isDispatchThread()
+ if token and self._command is not token: return
+ self._command = None
+ if not self.__disposed:
+ assert not self.__valid
+ if self._channel.getState() != channel.STATE_OPEN:
+ self.__error = None
+ self.__data = None
+ self.__error = error
+ self.__data = data
+ self.__valid = True
+ self.post()
+
+ def reset(self, data=None):
+ """
+ Force cache to become valid, cancel pending data retrieval if data is provided.
+ @param data - up-to-date data object (optional)
+ """
+ assert protocol.isDispatchThread()
+ if data is not None and self._command is not None:
+ self._command.cancel()
+ self._command = None
+ if not self.__disposed:
+ self.__data = data
+ self.__error = None
+ self.__valid = True
+ self.post()
+
+ def cancel(self):
+ """
+ Invalidate the cache.
+ Cancel pending data retrieval if any.
+ """
+ self.reset()
+ if self._command is not None:
+ self._command.cancel()
+ self._command = None
+
+ def dispose(self):
+ """
+ Dispose the cache.
+ Cancel pending data retrieval if any.
+ """
+ self.cancel()
+ self.__valid = True
+ self.__disposed = True
+
+ def __str__(self):
+ bf = cStringIO.StringIO()
+ bf.write('[')
+ if self.__valid: bf.append("valid,")
+ if self.__disposed: bf.write("disposed,")
+ if self.__posted: bf.write("posted,")
+ if self.__error is not None: bf.write("error,")
+ bf.write("data=")
+ bf.write(str(self.__data))
+ bf.write(']')
+ return bf.getvalue()
+
+ def startDataRetrieval(self):
+ """
+ Sub-classes should override this method to implement actual data retrieval logic.
+ @return True is all done, False if retrieval is in progress.
+ """
+ raise NotImplementedError("Abstract method")
diff --git a/python/src/tcf/util/event.py b/python/src/tcf/util/event.py
index 3e5e92118..2ca38df63 100644
--- a/python/src/tcf/util/event.py
+++ b/python/src/tcf/util/event.py
@@ -1,86 +1,86 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import threading
-from tcf import protocol, channel
-
-class DelegatingEventListener(channel.EventListener):
- def __init__(self, callable):
- self._callable = callable
- def event(self, name, data):
- try:
- args = channel.fromJSONSequence(data)
- self._callable(self.svc_name, name, *args)
- except Exception as x:
- protocol.log("Error decoding event data", x)
-
-def _print_event(service, name, *args):
- print "Event: %s.%s%s" % (service, name, tuple(args))
-
-def get_event_printer():
- return DelegatingEventListener(_print_event)
-
-class EventRecorder(object):
- def __init__(self, channel):
- self._channel = channel
- self._events = []
- self._listeners = {}
- self._lock = threading.RLock()
- self._filter = None
- def __del__(self):
- if self._channel.state == channel.STATE_OPEN:
- self.stop()
- def record(self, service, enable=True):
- with self._lock:
- listener = self._listeners.get(service)
- if listener:
- if not enable:
- protocol.invokeLater(self._channel.removeEventListener, service, listener)
- elif enable:
- recorder = self
- class Listener(channel.EventListener):
- def event(self, name, data):
- e = Event(service, name, data)
- recorder._event(e)
- listener = Listener()
- self._listeners[service] = listener
- protocol.invokeLater(self._channel.addEventListener, service, listener)
- self._recording = enable
- def stop(self, service=None):
- if service:
- self.record(service, False)
- else:
- for service in self._listeners.keys():
- self.record(service, False)
- def get(self):
- with self._lock:
- events = self._events
- self._events = []
- return events
- def _event(self, e):
- with self._lock:
- self._events.append(e)
- def __str__(self):
- events = self.get()
- return "\n".join(map(str, events))
- __repr__ = __str__
-
-class Event(object):
- def __init__(self, service, name, data):
- self.service = service
- self.name = name
- try:
- self.args = channel.fromJSONSequence(data)
- except Exception as x:
- protocol.log("Error decoding event data", x)
- def __str__(self):
- return "Event: %s.%s%s" % (self.service, self.name, tuple(self.args))
- __repr__ = __str__
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading
+from tcf import protocol, channel
+
+class DelegatingEventListener(channel.EventListener):
+ def __init__(self, callable):
+ self._callable = callable
+ def event(self, name, data):
+ try:
+ args = channel.fromJSONSequence(data)
+ self._callable(self.svc_name, name, *args)
+ except Exception as x:
+ protocol.log("Error decoding event data", x)
+
+def _print_event(service, name, *args):
+ print "Event: %s.%s%s" % (service, name, tuple(args))
+
+def get_event_printer():
+ return DelegatingEventListener(_print_event)
+
+class EventRecorder(object):
+ def __init__(self, channel):
+ self._channel = channel
+ self._events = []
+ self._listeners = {}
+ self._lock = threading.RLock()
+ self._filter = None
+ def __del__(self):
+ if self._channel.state == channel.STATE_OPEN:
+ self.stop()
+ def record(self, service, enable=True):
+ with self._lock:
+ listener = self._listeners.get(service)
+ if listener:
+ if not enable:
+ protocol.invokeLater(self._channel.removeEventListener, service, listener)
+ elif enable:
+ recorder = self
+ class Listener(channel.EventListener):
+ def event(self, name, data):
+ e = Event(service, name, data)
+ recorder._event(e)
+ listener = Listener()
+ self._listeners[service] = listener
+ protocol.invokeLater(self._channel.addEventListener, service, listener)
+ self._recording = enable
+ def stop(self, service=None):
+ if service:
+ self.record(service, False)
+ else:
+ for service in self._listeners.keys():
+ self.record(service, False)
+ def get(self):
+ with self._lock:
+ events = self._events
+ self._events = []
+ return events
+ def _event(self, e):
+ with self._lock:
+ self._events.append(e)
+ def __str__(self):
+ events = self.get()
+ return "\n".join(map(str, events))
+ __repr__ = __str__
+
+class Event(object):
+ def __init__(self, service, name, data):
+ self.service = service
+ self.name = name
+ try:
+ self.args = channel.fromJSONSequence(data)
+ except Exception as x:
+ protocol.log("Error decoding event data", x)
+ def __str__(self):
+ return "Event: %s.%s%s" % (self.service, self.name, tuple(self.args))
+ __repr__ = __str__
diff --git a/python/src/tcf/util/logging.py b/python/src/tcf/util/logging.py
index afe3037fc..0a15b5cde 100644
--- a/python/src/tcf/util/logging.py
+++ b/python/src/tcf/util/logging.py
@@ -1,54 +1,54 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-"Internal utility methods used for logging/tracing."
-
-from tcf import protocol
-import locale, time, cStringIO
-
-DECIMAL_DELIMITER = locale.localeconv().get('decimal_point', '.')
-
-def getDebugTime():
- """
- Returns a relative timestamp in the form "seconds,milliseconds". Each
- segment is zero-padded to three digits, ensuring a consistent length of
- seven characters. The timestamp has no absolute meaning. It is merely the
- elapsed time since January 1, 1970 UT truncated at 999 seconds. Do not
- use this for production code, especially for mathematically determining
- the relative time between two events, since the counter will flip to zero
- roughly every 16 minutes.
- """
- traceBuilder = cStringIO.StringIO()
-
- # Record the time
- tm = int(time.time() * 1000)
- seconds = (tm / 1000) % 1000
- if seconds < 100: traceBuilder.write('0')
- if seconds < 10: traceBuilder.write('0')
- traceBuilder.write(str(seconds))
- traceBuilder.write(DECIMAL_DELIMITER)
- millis = tm % 1000
- if millis < 100: traceBuilder.write('0')
- if millis < 10: traceBuilder.write('0')
- traceBuilder.write(str(millis))
- return traceBuilder.getvalue()
-
-def trace(msg):
- """
- Trace hooks should use this method to log a message. It prepends the
- message with a timestamp and sends it to the TCF logger facility. The
- logger implementation may or may not inject its own timestamp. For
- tracing, we definitely need one, so we introduce a minimal, relative-time
- stamp.
-
- @param msg the trace message
- """
- protocol.log('%s %s' % (getDebugTime(), msg))
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+"Internal utility methods used for logging/tracing."
+
+from tcf import protocol
+import locale, time, cStringIO
+
+DECIMAL_DELIMITER = locale.localeconv().get('decimal_point', '.')
+
+def getDebugTime():
+ """
+ Returns a relative timestamp in the form "seconds,milliseconds". Each
+ segment is zero-padded to three digits, ensuring a consistent length of
+ seven characters. The timestamp has no absolute meaning. It is merely the
+ elapsed time since January 1, 1970 UT truncated at 999 seconds. Do not
+ use this for production code, especially for mathematically determining
+ the relative time between two events, since the counter will flip to zero
+ roughly every 16 minutes.
+ """
+ traceBuilder = cStringIO.StringIO()
+
+ # Record the time
+ tm = int(time.time() * 1000)
+ seconds = (tm / 1000) % 1000
+ if seconds < 100: traceBuilder.write('0')
+ if seconds < 10: traceBuilder.write('0')
+ traceBuilder.write(str(seconds))
+ traceBuilder.write(DECIMAL_DELIMITER)
+ millis = tm % 1000
+ if millis < 100: traceBuilder.write('0')
+ if millis < 10: traceBuilder.write('0')
+ traceBuilder.write(str(millis))
+ return traceBuilder.getvalue()
+
+def trace(msg):
+ """
+ Trace hooks should use this method to log a message. It prepends the
+ message with a timestamp and sends it to the TCF logger facility. The
+ logger implementation may or may not inject its own timestamp. For
+ tracing, we definitely need one, so we introduce a minimal, relative-time
+ stamp.
+
+ @param msg the trace message
+ """
+ protocol.log('%s %s' % (getDebugTime(), msg))
diff --git a/python/src/tcf/util/sync.py b/python/src/tcf/util/sync.py
index d85434876..400c96526 100644
--- a/python/src/tcf/util/sync.py
+++ b/python/src/tcf/util/sync.py
@@ -1,222 +1,222 @@
-# *******************************************************************************
-# * Copyright (c) 2011 Wind River Systems, Inc. and others.
-# * All rights reserved. This program and the accompanying materials
-# * are made available under the terms of the Eclipse Public License v1.0
-# * which accompanies this distribution, and is available at
-# * http://www.eclipse.org/legal/epl-v10.html
-# *
-# * Contributors:
-# * Wind River Systems - initial API and implementation
-# *******************************************************************************
-
-import threading, types
-from tcf import protocol
-from tcf.channel.Command import Command
-
-class DispatchWrapper(object):
- "Simple wrapper for attribute access and invocation on TCF dispatch thread"
- def __init__(self, inner):
- self.inner = inner
- def __getattr__(self, attr):
- val = protocol.invokeAndWait(getattr, self.inner, attr)
- if type(val) in (types.FunctionType, types.MethodType):
- return DispatchWrapper(val)
- return val
- def __call__(self, *args, **kwargs):
- return protocol.invokeAndWait(self.inner, *args, **kwargs)
-
-class CommandControl(object):
- """Provides a simple interface to send commands to remote services
- and receive results.
-
- Usage:
- > cmd = CommandControl(channel)
- > cmd.<service>.<command>(<args>)
-
- Examples:
- # send command, but don't wait for result:
- > cmd.RunControl.suspend("system")
- # getE() returns the result and raises an exception in case of error response:
- > result = cmd.RunControl.getChildren(None).getE()
- # to get error and result at the same time, use this form:
- > error, result = cmd.Breakpoints.getIDs()
- """
- def __init__(self, channel, onDone=None, interactive=False):
- self._lock = threading.Condition()
- self._channel = channel
- self._onDone = onDone
- self._interactive = interactive
- self._queue = []
- self._pending = {}
- self._complete = []
- def __getattr__(self, attr):
- val = getattr(self._channel, attr, None)
- if val:
- if self._interactive and type(val) in (types.FunctionType, types.MethodType):
- val = DispatchWrapper(val)
- return val
- services = protocol.invokeAndWait(self._channel.getRemoteServices)
- if attr == "services":
- return services
- if attr in services:
- return ServiceWrapper(self, attr)
- raise AttributeError("Unknown service: %s. Use one of %s" % (attr, services))
- def invoke(self, service, command, *args, **kwargs):
- cmd = None
- if not protocol.isDispatchThread():
- if not kwargs.get("async"):
- cmd = protocol.invokeAndWait(self._invoke, service, command, *args, **kwargs)
- if cmd and self._interactive:
- return cmd.getE()
- else:
- with self._lock:
- self._queue.append((service, command, args, kwargs))
- if len(self._queue) == 1:
- protocol.invokeLater(self._processQueue)
- return
- return cmd
- def _invoke(self, service, command, *args, **kwargs):
- cmdCtrl = self
- class GenericCommand(Command):
- _result = None
- def done(self, error, args):
- resultArgs = None
- if not error and args:
- # error result is usually in args[0], but there are exceptions
- if service == "StackTrace" and command == "getContext":
- error = self.toError(args[1])
- resultArgs = (args[0],)
- elif service == "Expressions" and command == "evaluate":
- error = self.toError(args[1])
- resultArgs = (args[0], args[2])
- elif service == "FileSystem" and command in ('read', 'readdir', 'roots'):
- error = self.toError(args[1])
- resultArgs = (args[0],) + tuple(args[2:])
- elif service == "Diagnostics" and command.startswith("echo"):
- resultArgs = (args[0],)
- else:
- error = self.toError(args[0])
- resultArgs = args[1:]
- cmdCtrl._doneCommand(self.token, error, resultArgs)
- def wait(self, timeout=None):
- cmdCtrl._waitForCommand(self.token, timeout)
- def cancel(self):
- return protocol.invokeAndWait(self.token.cancel)
- def getResult(self, wait=None):
- if wait:
- cmdCtrl._waitForCommand(self.token)
- return self._result
- def getE(self):
- r = self.getResult(True)
- if r.error:
- raise r.error
- return r.args
- def get(self):
- r = self.getResult(True)
- return r.args
- def getError(self):
- r = self.getResult(True)
- return r.error
- def __str__(self):
- if self._async:
- return self.getCommandString()
- return str(self.get())
- def __iter__(self):
- return iter(self.getResult(True))
- cmd = GenericCommand(self._channel, service, command, args)
- cmd._async = kwargs.get("async")
- cmd._onDone = kwargs.get("onDone")
- self._addPending(cmd)
- return cmd
- def _processQueue(self):
- assert protocol.isDispatchThread()
- with self._lock:
- for cmd in self._queue:
- service, command, args, kwargs = cmd
- self._invoke(service, command, *args, **kwargs)
- del self._queue[:]
- def _addPending(self, cmd):
- with self._lock:
- self._pending[cmd.token.id] = cmd
- self._lock.notifyAll()
- def _doneCommand(self, token, error, args):
- with self._lock:
- cmd = self._pending.get(token.id)
- assert cmd
- del self._pending[token.id]
- cmd._result = CommandResult(token, error, args)
- if cmd._async: self._complete.append(cmd)
- isDone = self.isDone()
- if isDone: self._lock.notifyAll()
- if cmd._onDone:
- if args is None: args = (None,)
- cmd._onDone(error, *args)
- if isDone and self._onDone: self._onDone()
- def isDone(self):
- with self._lock:
- return not self._pending and not self._queue
- def wait(self, timeout=None):
- assert not protocol.isDispatchThread()
- with self._lock:
- while self._pending or self._queue:
- self._lock.wait(timeout)
- if timeout: break
- def _waitForCommand(self, token, timeout=None):
- assert not protocol.isDispatchThread()
- with self._lock:
- while token.id in self._pending:
- self._lock.wait(timeout)
- if timeout: break
- else:
- if self._queue:
- self._lock.wait(timeout)
- while token.id in self._pending:
- self._lock.wait(timeout)
- if timeout: break
- def cancel(self):
- if not protocol.isDispatchThread():
- protocol.invokeLater(self.cancel)
- return
- with self._lock:
- for cmd in self._pending.values():
- cmd.token.cancel()
- del self._queue[:]
- def getResult(self, wait=True):
- if wait:
- self.wait()
- with self._lock:
- result = map(lambda c: c.getResult(), self._complete)
- del self._complete[:]
- return result
-
-class CommandResult(object):
- def __init__(self, token, error, args):
- self.token = token
- self.error = error
- # unwrap result if only one element
- if args and len(args) == 1:
- args = args[0]
- self.args = args
- def __str__(self):
- if self.error:
- return "[%s] error: %s" % (self.token.id, self.error)
- return "[%s] result: %s" % (self.token.id, self.args)
- __repr__ = __str__
- def __iter__(self):
- yield self.error
- yield self.args
-
-class ServiceWrapper(object):
- def __init__(self, control, service):
- self._control = control
- self._service = service
- def __getattr__(self, attr):
- return CommandWrapper(self._control, self._service, attr)
-
-class CommandWrapper(object):
- def __init__(self, control, service, command):
- self._control = control
- self._service = service
- self._command = command
- def __call__(self, *args, **kwargs):
- return self._control.invoke(self._service, self._command, *args, **kwargs)
+# *******************************************************************************
+# * Copyright (c) 2011 Wind River Systems, Inc. and others.
+# * All rights reserved. This program and the accompanying materials
+# * are made available under the terms of the Eclipse Public License v1.0
+# * which accompanies this distribution, and is available at
+# * http://www.eclipse.org/legal/epl-v10.html
+# *
+# * Contributors:
+# * Wind River Systems - initial API and implementation
+# *******************************************************************************
+
+import threading, types
+from tcf import protocol
+from tcf.channel.Command import Command
+
+class DispatchWrapper(object):
+ "Simple wrapper for attribute access and invocation on TCF dispatch thread"
+ def __init__(self, inner):
+ self.inner = inner
+ def __getattr__(self, attr):
+ val = protocol.invokeAndWait(getattr, self.inner, attr)
+ if type(val) in (types.FunctionType, types.MethodType):
+ return DispatchWrapper(val)
+ return val
+ def __call__(self, *args, **kwargs):
+ return protocol.invokeAndWait(self.inner, *args, **kwargs)
+
+class CommandControl(object):
+ """Provides a simple interface to send commands to remote services
+ and receive results.
+
+ Usage:
+ > cmd = CommandControl(channel)
+ > cmd.<service>.<command>(<args>)
+
+ Examples:
+ # send command, but don't wait for result:
+ > cmd.RunControl.suspend("system")
+ # getE() returns the result and raises an exception in case of error response:
+ > result = cmd.RunControl.getChildren(None).getE()
+ # to get error and result at the same time, use this form:
+ > error, result = cmd.Breakpoints.getIDs()
+ """
+ def __init__(self, channel, onDone=None, interactive=False):
+ self._lock = threading.Condition()
+ self._channel = channel
+ self._onDone = onDone
+ self._interactive = interactive
+ self._queue = []
+ self._pending = {}
+ self._complete = []
+ def __getattr__(self, attr):
+ val = getattr(self._channel, attr, None)
+ if val:
+ if self._interactive and type(val) in (types.FunctionType, types.MethodType):
+ val = DispatchWrapper(val)
+ return val
+ services = protocol.invokeAndWait(self._channel.getRemoteServices)
+ if attr == "services":
+ return services
+ if attr in services:
+ return ServiceWrapper(self, attr)
+ raise AttributeError("Unknown service: %s. Use one of %s" % (attr, services))
+ def invoke(self, service, command, *args, **kwargs):
+ cmd = None
+ if not protocol.isDispatchThread():
+ if not kwargs.get("async"):
+ cmd = protocol.invokeAndWait(self._invoke, service, command, *args, **kwargs)
+ if cmd and self._interactive:
+ return cmd.getE()
+ else:
+ with self._lock:
+ self._queue.append((service, command, args, kwargs))
+ if len(self._queue) == 1:
+ protocol.invokeLater(self._processQueue)
+ return
+ return cmd
+ def _invoke(self, service, command, *args, **kwargs):
+ cmdCtrl = self
+ class GenericCommand(Command):
+ _result = None
+ def done(self, error, args):
+ resultArgs = None
+ if not error and args:
+ # error result is usually in args[0], but there are exceptions
+ if service == "StackTrace" and command == "getContext":
+ error = self.toError(args[1])
+ resultArgs = (args[0],)
+ elif service == "Expressions" and command == "evaluate":
+ error = self.toError(args[1])
+ resultArgs = (args[0], args[2])
+ elif service == "FileSystem" and command in ('read', 'readdir', 'roots'):
+ error = self.toError(args[1])
+ resultArgs = (args[0],) + tuple(args[2:])
+ elif service == "Diagnostics" and command.startswith("echo"):
+ resultArgs = (args[0],)
+ else:
+ error = self.toError(args[0])
+ resultArgs = args[1:]
+ cmdCtrl._doneCommand(self.token, error, resultArgs)
+ def wait(self, timeout=None):
+ cmdCtrl._waitForCommand(self.token, timeout)
+ def cancel(self):
+ return protocol.invokeAndWait(self.token.cancel)
+ def getResult(self, wait=None):
+ if wait:
+ cmdCtrl._waitForCommand(self.token)
+ return self._result
+ def getE(self):
+ r = self.getResult(True)
+ if r.error:
+ raise r.error
+ return r.args
+ def get(self):
+ r = self.getResult(True)
+ return r.args
+ def getError(self):
+ r = self.getResult(True)
+ return r.error
+ def __str__(self):
+ if self._async:
+ return self.getCommandString()
+ return str(self.get())
+ def __iter__(self):
+ return iter(self.getResult(True))
+ cmd = GenericCommand(self._channel, service, command, args)
+ cmd._async = kwargs.get("async")
+ cmd._onDone = kwargs.get("onDone")
+ self._addPending(cmd)
+ return cmd
+ def _processQueue(self):
+ assert protocol.isDispatchThread()
+ with self._lock:
+ for cmd in self._queue:
+ service, command, args, kwargs = cmd
+ self._invoke(service, command, *args, **kwargs)
+ del self._queue[:]
+ def _addPending(self, cmd):
+ with self._lock:
+ self._pending[cmd.token.id] = cmd
+ self._lock.notifyAll()
+ def _doneCommand(self, token, error, args):
+ with self._lock:
+ cmd = self._pending.get(token.id)
+ assert cmd
+ del self._pending[token.id]
+ cmd._result = CommandResult(token, error, args)
+ if cmd._async: self._complete.append(cmd)
+ isDone = self.isDone()
+ if isDone: self._lock.notifyAll()
+ if cmd._onDone:
+ if args is None: args = (None,)
+ cmd._onDone(error, *args)
+ if isDone and self._onDone: self._onDone()
+ def isDone(self):
+ with self._lock:
+ return not self._pending and not self._queue
+ def wait(self, timeout=None):
+ assert not protocol.isDispatchThread()
+ with self._lock:
+ while self._pending or self._queue:
+ self._lock.wait(timeout)
+ if timeout: break
+ def _waitForCommand(self, token, timeout=None):
+ assert not protocol.isDispatchThread()
+ with self._lock:
+ while token.id in self._pending:
+ self._lock.wait(timeout)
+ if timeout: break
+ else:
+ if self._queue:
+ self._lock.wait(timeout)
+ while token.id in self._pending:
+ self._lock.wait(timeout)
+ if timeout: break
+ def cancel(self):
+ if not protocol.isDispatchThread():
+ protocol.invokeLater(self.cancel)
+ return
+ with self._lock:
+ for cmd in self._pending.values():
+ cmd.token.cancel()
+ del self._queue[:]
+ def getResult(self, wait=True):
+ if wait:
+ self.wait()
+ with self._lock:
+ result = map(lambda c: c.getResult(), self._complete)
+ del self._complete[:]
+ return result
+
+class CommandResult(object):
+ def __init__(self, token, error, args):
+ self.token = token
+ self.error = error
+ # unwrap result if only one element
+ if args and len(args) == 1:
+ args = args[0]
+ self.args = args
+ def __str__(self):
+ if self.error:
+ return "[%s] error: %s" % (self.token.id, self.error)
+ return "[%s] result: %s" % (self.token.id, self.args)
+ __repr__ = __str__
+ def __iter__(self):
+ yield self.error
+ yield self.args
+
+class ServiceWrapper(object):
+ def __init__(self, control, service):
+ self._control = control
+ self._service = service
+ def __getattr__(self, attr):
+ return CommandWrapper(self._control, self._service, attr)
+
+class CommandWrapper(object):
+ def __init__(self, control, service, command):
+ self._control = control
+ self._service = service
+ self._command = command
+ def __call__(self, *args, **kwargs):
+ return self._control.invoke(self._service, self._command, *args, **kwargs)
diff --git a/python/src/tcf/util/task.py b/python/src/tcf/util/task.py
index a31d49a6e..c541dea6a 100644
--- a/python/src/tcf/util/task.py
+++ b/python/src/tcf/util/task.py
@@ -1,180 +1,180 @@
-#******************************************************************************
-# Copyright (c) 2011 Wind River Systems, Inc. and others.
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Eclipse Public License v1.0
-# which accompanies this distribution, and is available at
-# http://www.eclipse.org/legal/epl-v10.html
-#
-# Contributors:
-# Wind River Systems - initial API and implementation
-#******************************************************************************
-
-import threading
-from tcf import protocol, channel
-
-class Task(object):
- """
- A <tt>Task</tt> is an utility class that represents the result of an asynchronous
- communication over TCF framework. Methods are provided to check if the communication is
- complete, to wait for its completion, and to retrieve the result of
- the communication.
-
- Task is useful when communication is requested by a thread other then TCF dispatch thread.
- If client has a global state, for example, cached remote data, multithreading should be avoided,
- because it is extremely difficult to ensure absence of racing conditions or deadlocks in such environment.
- Such clients should consider message driven design, see DataCache and its usage as an example.
-
- If a client is extending Task it should implement run() method to perform actual communications.
- The run() method will be execute by TCF dispatch thread, and client code should then call either done() or
- error() to indicate that task computations are complete.
- """
- __result = None
- __is_done = False
- __error = None
- __canceled = False
- __channel_listener = None
-
- def __init__(self, target=None, *args, **kwargs):
- """
- Construct a TCF task object and schedule it for execution.
- """
- if target:
- kwargs["done"] = self.__done
- else:
- target = self.run
-
- self._target = target
- self._args = args
- self._kwargs = kwargs
- self._lock = threading.Condition()
- self.__channel = kwargs.pop("channel", None)
- protocol.invokeLater(self.__doRun)
- timeout = kwargs.pop("timeout", None)
- if timeout:
- protocol.invokeLaterWithDelay(timeout, self.cancel)
-
- def __doRun(self):
- try:
- if self.__channel:
- if self.__channel.getState() != channel.STATE_OPEN:
- raise Exception("Channel is closed")
- task = self
- class CancelOnClose(channel.ChannelListener):
- def onChannelClosed(self, error):
- task.cancel(True)
- self.__channel_listener = CancelOnClose()
- self.__channel.addChannelListener(self.__channel_listener)
- self._target(*self._args, **self._kwargs)
- except Exception as x:
- if not self.__is_done and self.__error is None:
- self.error(x)
-
- def __done(self, error, result):
- if error:
- self.error(error)
- else:
- self.done(result)
-
- def run(self, *args, **kwargs):
- raise NotImplementedError("Abstract method")
-
- def done(self, result):
- with self._lock:
- assert protocol.isDispatchThread()
- if self.__canceled: return
- assert not self.__is_done
- assert not self.__error
- assert self.__result is None
- self.__result = result
- self.__is_done = True
- if self.__channel:
- self.__channel.removeChannelListener(self.__channel_listener)
- self._lock.notifyAll()
-
- def error(self, error):
- """
- Set a error and notify all threads waiting for the task to complete.
- The method is supposed to be called in response to executing of run() method of this task.
-
- @param error - computation error.
- """
- assert protocol.isDispatchThread()
- assert error
- with self._lock:
- if self.__canceled: return
- assert self.__error is None
- assert self.__result is None
- assert not self.__is_done
- self.__error = error
- if self.__channel:
- self.__channel.removeChannelListener(self.__channel_listener)
- self._lock.notifyAll()
-
- def cancel(self):
- assert protocol.isDispatchThread()
- with self._lock:
- if self.isDone(): return False
- self.__canceled = True
- self.__error = Exception("Canceled")
- if self.__channel:
- self.__channel.removeChannelListener(self.__channel_listener)
- self._lock.notifyAll()
- return True
-
- def get(self, timeout=None):
- """
- Waits if necessary for the computation to complete, and then
- retrieves its result.
-
- @return the computed result
- @throws CancellationException if the computation was canceled
- @throws ExecutionException if the computation threw an
- exception
- @throws InterruptedException if the current thread was interrupted
- while waiting
- """
- assert not protocol.isDispatchThread()
- with self._lock:
- while not self.isDone():
- self._lock.wait(timeout)
- if timeout and not self.isDone():
- raise TimeoutException("Timed out")
- if self.__error:
- raise Exception("TCF task aborted", self.__error)
- return self.__result
-
- def isCancelled(self):
- """
- Returns <tt>true</tt> if this task was canceled before it completed
- normally.
-
- @return <tt>true</tt> if task was canceled before it completed
- """
- with self._lock:
- return self.__canceled
-
- def isDone(self):
- """
- Returns <tt>true</tt> if this task completed.
-
- Completion may be due to normal termination, an exception, or
- cancellation -- in all of these cases, this method will return
- <tt>true</tt>.
-
- @return <tt>true</tt> if this task completed.
- """
- with self._lock:
- return self.__error or self.__is_done
-
- def getError(self):
- """
- Return task execution error if any.
- @return Exception object or None
- """
- return self.__error
-
- def getResult(self):
- return self.__result
-
-class TimeoutException(Exception):
- pass
+#******************************************************************************
+# Copyright (c) 2011 Wind River Systems, Inc. and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# Wind River Systems - initial API and implementation
+#******************************************************************************
+
+import threading
+from tcf import protocol, channel
+
+class Task(object):
+ """
+ A <tt>Task</tt> is an utility class that represents the result of an asynchronous
+ communication over TCF framework. Methods are provided to check if the communication is
+ complete, to wait for its completion, and to retrieve the result of
+ the communication.
+
+ Task is useful when communication is requested by a thread other then TCF dispatch thread.
+ If client has a global state, for example, cached remote data, multithreading should be avoided,
+ because it is extremely difficult to ensure absence of racing conditions or deadlocks in such environment.
+ Such clients should consider message driven design, see DataCache and its usage as an example.
+
+ If a client is extending Task it should implement run() method to perform actual communications.
+ The run() method will be execute by TCF dispatch thread, and client code should then call either done() or
+ error() to indicate that task computations are complete.
+ """
+ __result = None
+ __is_done = False
+ __error = None
+ __canceled = False
+ __channel_listener = None
+
+ def __init__(self, target=None, *args, **kwargs):
+ """
+ Construct a TCF task object and schedule it for execution.
+ """
+ if target:
+ kwargs["done"] = self.__done
+ else:
+ target = self.run
+
+ self._target = target
+ self._args = args
+ self._kwargs = kwargs
+ self._lock = threading.Condition()
+ self.__channel = kwargs.pop("channel", None)
+ protocol.invokeLater(self.__doRun)
+ timeout = kwargs.pop("timeout", None)
+ if timeout:
+ protocol.invokeLaterWithDelay(timeout, self.cancel)
+
+ def __doRun(self):
+ try:
+ if self.__channel:
+ if self.__channel.getState() != channel.STATE_OPEN:
+ raise Exception("Channel is closed")
+ task = self
+ class CancelOnClose(channel.ChannelListener):
+ def onChannelClosed(self, error):
+ task.cancel(True)
+ self.__channel_listener = CancelOnClose()
+ self.__channel.addChannelListener(self.__channel_listener)
+ self._target(*self._args, **self._kwargs)
+ except Exception as x:
+ if not self.__is_done and self.__error is None:
+ self.error(x)
+
+ def __done(self, error, result):
+ if error:
+ self.error(error)
+ else:
+ self.done(result)
+
+ def run(self, *args, **kwargs):
+ raise NotImplementedError("Abstract method")
+
+ def done(self, result):
+ with self._lock:
+ assert protocol.isDispatchThread()
+ if self.__canceled: return
+ assert not self.__is_done
+ assert not self.__error
+ assert self.__result is None
+ self.__result = result
+ self.__is_done = True
+ if self.__channel:
+ self.__channel.removeChannelListener(self.__channel_listener)
+ self._lock.notifyAll()
+
+ def error(self, error):
+ """
+ Set a error and notify all threads waiting for the task to complete.
+ The method is supposed to be called in response to executing of run() method of this task.
+
+ @param error - computation error.
+ """
+ assert protocol.isDispatchThread()
+ assert error
+ with self._lock:
+ if self.__canceled: return
+ assert self.__error is None
+ assert self.__result is None
+ assert not self.__is_done
+ self.__error = error
+ if self.__channel:
+ self.__channel.removeChannelListener(self.__channel_listener)
+ self._lock.notifyAll()
+
+ def cancel(self):
+ assert protocol.isDispatchThread()
+ with self._lock:
+ if self.isDone(): return False
+ self.__canceled = True
+ self.__error = Exception("Canceled")
+ if self.__channel:
+ self.__channel.removeChannelListener(self.__channel_listener)
+ self._lock.notifyAll()
+ return True
+
+ def get(self, timeout=None):
+ """
+ Waits if necessary for the computation to complete, and then
+ retrieves its result.
+
+ @return the computed result
+ @throws CancellationException if the computation was canceled
+ @throws ExecutionException if the computation threw an
+ exception
+ @throws InterruptedException if the current thread was interrupted
+ while waiting
+ """
+ assert not protocol.isDispatchThread()
+ with self._lock:
+ while not self.isDone():
+ self._lock.wait(timeout)
+ if timeout and not self.isDone():
+ raise TimeoutException("Timed out")
+ if self.__error:
+ raise Exception("TCF task aborted", self.__error)
+ return self.__result
+
+ def isCancelled(self):
+ """
+ Returns <tt>true</tt> if this task was canceled before it completed
+ normally.
+
+ @return <tt>true</tt> if task was canceled before it completed
+ """
+ with self._lock:
+ return self.__canceled
+
+ def isDone(self):
+ """
+ Returns <tt>true</tt> if this task completed.
+
+ Completion may be due to normal termination, an exception, or
+ cancellation -- in all of these cases, this method will return
+ <tt>true</tt>.
+
+ @return <tt>true</tt> if this task completed.
+ """
+ with self._lock:
+ return self.__error or self.__is_done
+
+ def getError(self):
+ """
+ Return task execution error if any.
+ @return Exception object or None
+ """
+ return self.__error
+
+ def getResult(self):
+ return self.__result
+
+class TimeoutException(Exception):
+ pass

Back to the top