Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/com.windriver.tcf.api/src/com/windriver/tcf/api/internal/services/remote/MemoryProxy.java')
-rw-r--r--plugins/com.windriver.tcf.api/src/com/windriver/tcf/api/internal/services/remote/MemoryProxy.java366
1 files changed, 366 insertions, 0 deletions
diff --git a/plugins/com.windriver.tcf.api/src/com/windriver/tcf/api/internal/services/remote/MemoryProxy.java b/plugins/com.windriver.tcf.api/src/com/windriver/tcf/api/internal/services/remote/MemoryProxy.java
new file mode 100644
index 000000000..19b3e1aa4
--- /dev/null
+++ b/plugins/com.windriver.tcf.api/src/com/windriver/tcf/api/internal/services/remote/MemoryProxy.java
@@ -0,0 +1,366 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package com.windriver.tcf.api.internal.services.remote;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import com.windriver.tcf.api.core.Base64;
+import com.windriver.tcf.api.core.Command;
+import com.windriver.tcf.api.internal.core.ReadOnlyMap;
+import com.windriver.tcf.api.protocol.IChannel;
+import com.windriver.tcf.api.protocol.IToken;
+import com.windriver.tcf.api.protocol.JSON;
+import com.windriver.tcf.api.services.IMemory;
+
+public class MemoryProxy implements IMemory {
+
+ private final IChannel channel;
+ private final Map<MemoryListener,IChannel.IEventListener> listeners =
+ new HashMap<MemoryListener,IChannel.IEventListener>();
+
+ private static class Range implements Comparable<Range> {
+ int offs;
+ int size;
+ int stat;
+ String msg;
+
+ public int compareTo(Range o) {
+ if (offs < o.offs) return -1;
+ if (offs > o.offs) return +1;
+ return 0;
+ }
+ }
+
+ private class MemoryErrorReport extends MemoryError implements ErrorOffset {
+
+ private static final long serialVersionUID = 796525409870265390L;
+ private final Range[] ranges;
+
+ @SuppressWarnings("unchecked")
+ MemoryErrorReport(String msg, Number addr, Object ranges) {
+ super(msg);
+ Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)ranges;
+ this.ranges = new Range[c.size()];
+ int n = 0;
+ BigInteger addr_bi = addr instanceof BigInteger ?
+ (BigInteger)addr : new BigInteger(addr.toString());
+ for (Map<String,Object> m : c) {
+ Range r = new Range();
+ Number x = (Number)m.get("addr");
+ BigInteger y = x instanceof BigInteger ?
+ (BigInteger)x : new BigInteger(x.toString());
+ r.offs = addr_bi.subtract(y).intValue();
+ r.size = ((Number)m.get("size")).intValue();
+ r.stat = ((Number)m.get("stat")).intValue();
+ r.msg = Command.toErrorString(m.get("msg"));
+ assert r.offs >= 0;
+ assert r.size >= 0;
+ this.ranges[n++] = r;
+ }
+ Arrays.sort(this.ranges);
+ }
+
+ public String getMessage(int offset) {
+ int l = 0;
+ int h = ranges.length - 1;
+ while (l <= h) {
+ int n = (l + h) / 2;
+ Range r = ranges[n];
+ if (r.offs > offset) {
+ h = n - 1;
+ }
+ else if (offset >= r.offs + r.size) {
+ l = n + 1;
+ }
+ else {
+ return r.msg;
+ }
+ }
+ return null;
+ }
+
+ public int getStatus(int offset) {
+ int l = 0;
+ int h = ranges.length - 1;
+ while (l <= h) {
+ int n = (l + h) / 2;
+ Range r = ranges[n];
+ if (r.offs > offset) {
+ h = n - 1;
+ }
+ else if (offset >= r.offs + r.size) {
+ l = n + 1;
+ }
+ else {
+ return r.stat;
+ }
+ }
+ return BYTE_UNKNOWN;
+ }
+ }
+
+ private class MemContext implements MemoryContext {
+
+ private final Map<String,Object> props;
+
+ MemContext(Map<String,Object> props) {
+ assert props instanceof ReadOnlyMap;
+ this.props = props;
+ }
+
+ public String getID() {
+ return (String)props.get(PROP_ID);
+ }
+
+ public String getParentID() {
+ String s = (String)props.get(PROP_PARENT_ID);
+ if (s == null) return "";
+ return s;
+ }
+
+ public int getAddressSize() {
+ Number n = (Number)props.get(PROP_ADDRESS_SIZE);
+ if (n == null) return 0;
+ return n.intValue();
+ }
+
+ public int getProcessID() {
+ Number n = (Number)props.get(PROP_PROCESS_ID);
+ if (n == null) return 0;
+ return n.intValue();
+ }
+
+ public boolean isBigEndian() {
+ Boolean n = (Boolean)props.get(PROP_BIG_ENDIAN);
+ if (n == null) return false;
+ return n.booleanValue();
+ }
+
+ public Map<String, Object> getProperties() {
+ return props;
+ }
+
+ public IToken fill(final Number addr, int word_size,
+ byte[] value, int size, int mode, final DoneMemory done) {
+ return new MemoryCommand("fill", new Object[] {
+ getID(), addr, word_size, size, mode, value
+ } ) {
+ public void done(Exception error, Object[] args) {
+ MemoryError e = null;
+ if (error != null) {
+ e = new MemoryError(error.getMessage());
+ }
+ else {
+ assert args.length == 3;
+ e = toMemoryError(addr, args[0], args[1], args[2]);
+ }
+ done.doneMemory(token, e);
+ }
+ }.token;
+ }
+
+ public IToken get(final Number addr, int word_size,
+ final byte[] buf, final int offs, final int size,
+ int mode, final DoneMemory done) {
+ return new MemoryCommand("get", new Object[] {
+ getID(), addr, word_size, size, mode
+ } ) {
+ public void done(Exception error, Object[] args) {
+ MemoryError e = null;
+ if (error != null) {
+ e = new MemoryError(error.getMessage());
+ }
+ else {
+ assert args.length == 4;
+ String str = (String)args[0];
+ if (str != null) Base64.toByteArray(buf, offs, size, str.toCharArray());
+ e = toMemoryError(addr, args[1], args[2], args[3]);
+ }
+ done.doneMemory(token, e);
+ }
+ }.token;
+ }
+
+ public IToken set(final Number addr, int word_size,
+ byte[] buf, int offs, int size, int mode, final DoneMemory done) {
+ return new MemoryCommand("set", new Object[] {
+ getID(), addr, word_size, size, mode, Base64.toBase64(buf, offs, size)
+ } ) {
+ public void done(Exception error, Object[] args) {
+ MemoryError e = null;
+ if (error != null) {
+ e = new MemoryError(error.getMessage());
+ }
+ else {
+ assert args.length == 3;
+ e = toMemoryError(addr, args[0], args[1], args[2]);
+ }
+ done.doneMemory(token, e);
+ }
+ }.token;
+ }
+
+ public String toString() {
+ return "[Memory Context " + props.toString() + "]";
+ }
+ }
+
+ public MemoryProxy(IChannel channel) {
+ this.channel = channel;
+ }
+
+ public void addListener(final MemoryListener listener) {
+ IChannel.IEventListener l = new IChannel.IEventListener() {
+
+ public void event(String name, byte[] data) {
+ try {
+ Object[] args = JSON.parseSequence(data);
+ if (name.equals("contextAdded")) {
+ assert args.length == 1;
+ listener.contextAdded(toContextArray(args[0]));
+ }
+ else if (name.equals("contextChanged")) {
+ assert args.length == 1;
+ listener.contextChanged(toContextArray(args[0]));
+ }
+ else if (name.equals("contextRemoved")) {
+ assert args.length == 1;
+ listener.contextRemoved(toStringArray(args[0]));
+ }
+ else if (name.equals("memoryChanged")) {
+ assert args.length == 2;
+ listener.memoryChanged((String)args[0],
+ toAddrArray(args[1]), toSizeArray(args[1]));
+ }
+ else {
+ throw new IOException("Memory service: unknown event: " + name);
+ }
+ }
+ catch (Throwable x) {
+ channel.terminate(x);
+ }
+ }
+ };
+ channel.addEventListener(this, l);
+ listeners.put(listener, l);
+ }
+
+ public void removeListener(MemoryListener listener) {
+ IChannel.IEventListener l = listeners.remove(listener);
+ if (l != null) channel.removeEventListener(this, l);
+ }
+
+ public IToken getContext(String context_id, final DoneGetContext done) {
+ return new Command(channel, this, "getContext", new Object[]{ context_id }) {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void done(Exception error, Object[] args) {
+ MemContext ctx = null;
+ if (error == null) {
+ assert args.length == 3;
+ error = toError(args[0], args[1]);
+ if (args[2] != null) {
+ ctx = new MemContext((Map<String,Object>)args[2]);
+ }
+ }
+ done.doneGetContext(token, error, ctx);
+ }
+ }.token;
+ }
+
+ public IToken getChildren(String parent_context_id, final DoneGetChildren done) {
+ return new Command(channel, this, "getChildren", new Object[]{ parent_context_id }) {
+ @Override
+ public void done(Exception error, Object[] args) {
+ String[] arr = null;
+ if (error == null) {
+ assert args.length == 3;
+ error = toError(args[0], args[1]);
+ arr = toStringArray(args[2]);
+ }
+ done.doneGetChildren(token, error, arr);
+ }
+ }.token;
+ }
+
+ public String getName() {
+ return NAME;
+ }
+
+ private abstract class MemoryCommand extends Command {
+
+ MemoryCommand(String cmd, Object[] args) {
+ super(channel, MemoryProxy.this, cmd, args);
+ }
+
+ MemoryError toMemoryError(Number addr, Object code, Object data, Object ranges) {
+ int error_code = ((Number)code).intValue();
+ if (error_code == 0) return null;
+ String cmd = getCommandString();
+ if (cmd.length() > 72) cmd = cmd.substring(0, 72) + "...";
+ return new MemoryErrorReport(
+ "TCF command exception:" +
+ "\nCommand: " + cmd +
+ "\nException: " + toErrorString(data) +
+ "\nError code: " + code, addr, ranges);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private MemoryContext[] toContextArray(Object o) {
+ Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)o;
+ if (c == null) return new MemoryContext[0];
+ int n = 0;
+ MemoryContext[] ctx = new MemoryContext[c.size()];
+ for (Iterator<Map<String,Object>> i = c.iterator(); i.hasNext();) {
+ ctx[n++] = new MemContext(i.next());
+ }
+ return ctx;
+ }
+
+ @SuppressWarnings("unchecked")
+ private long[] toSizeArray(Object o) {
+ Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)o;
+ if (c == null) return null;
+ long[] a = new long[c.size()];
+ int n = 0;
+ for (Map<String,Object> m : c) {
+ Number sz = (Number)m.get("size");
+ a[n++] = sz == null ? 0 : sz.longValue();
+ }
+ return a;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Number[] toAddrArray(Object o) {
+ Collection<Map<String,Object>> c = (Collection<Map<String,Object>>)o;
+ if (c == null) return null;
+ Number[] a = new Number[c.size()];
+ int n = 0;
+ for (Map<String,Object> m : c) {
+ a[n++] = (Number)m.get("addr");
+ }
+ return a;
+ }
+
+ @SuppressWarnings("unchecked")
+ private String[] toStringArray(Object o) {
+ Collection<String> c = (Collection<String>)o;
+ if (c == null) return new String[0];
+ return (String[])c.toArray(new String[c.size()]);
+ }
+}

Back to the top