diff options
author | Anton Leherbauer | 2012-01-23 09:28:01 +0000 |
---|---|---|
committer | Anton Leherbauer | 2012-01-23 09:28:01 +0000 |
commit | 6f047bf6a21dcc9be9bf444da123e8b32834da52 (patch) | |
tree | 22cc2972f8bfa7a3693aa514ecef25581dd2dd32 /python | |
parent | a1b540e1272eda3d1b09f3232512db9cc0f1d168 (diff) | |
download | org.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.tar.gz org.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.tar.xz org.eclipse.tcf-6f047bf6a21dcc9be9bf444da123e8b32834da52.zip |
TCF Python: Unify line endings.
Diffstat (limited to 'python')
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 |