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, |