diff options
author | Sverker Eriksson <[email protected]> | 2015-11-20 19:45:29 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2016-04-07 18:41:47 +0200 |
commit | 539ce190ba8f8842c24b17f3257c44cd850d7e01 (patch) | |
tree | 44fdc375d19068ca9434f943bb3d23bdfe79c570 /lib/jinterface/java_src | |
parent | 9c80b9ec06fc0ca89dcc8d797a2dbc408a162098 (diff) | |
download | otp-539ce190ba8f8842c24b17f3257c44cd850d7e01.tar.gz otp-539ce190ba8f8842c24b17f3257c44cd850d7e01.tar.bz2 otp-539ce190ba8f8842c24b17f3257c44cd850d7e01.zip |
jinterface: Support 32-bit creation values
Diffstat (limited to 'lib/jinterface/java_src')
6 files changed, 279 insertions, 74 deletions
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java index 20b7ff6a7f..66b4475a9e 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPid.java @@ -27,6 +27,7 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object> // don't change this! private static final long serialVersionUID = 1664394142301803659L; + private final int tag; private final String node; private final int id; private final int serial; @@ -44,6 +45,7 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object> public OtpErlangPid(final OtpLocalNode self) { final OtpErlangPid p = self.createPid(); + tag = p.tag; id = p.id; serial = p.serial; creation = p.creation; @@ -65,6 +67,7 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object> throws OtpErlangDecodeException { final OtpErlangPid p = buf.read_pid(); + tag = p.tag; node = p.node(); id = p.id(); serial = p.serial(); @@ -85,15 +88,52 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object> * used. * * @param creation - * yet another arbitrary number. Only the low order 2 bits will + * yet another arbitrary number. Ony the low order 2 bits will * be used. */ public OtpErlangPid(final String node, final int id, final int serial, - final int creation) { - this.node = node; - this.id = id & 0x7fff; // 15 bits - this.serial = serial & 0x1fff; // 13 bits - this.creation = creation & 0x03; // 2 bits + final int creation) { + this(OtpExternal.pidTag, node, id, serial, creation); + } + + /** + * Create an Erlang pid from its components. + * + * @param tag + * the external format to be compliant with + * OtpExternal.pidTag where only a subset of the bits are significant (see other constructor). + * OtpExternal.newPidTag where all 32 bits of id,serial and creation are significant. + * newPidTag can only be decoded by OTP-19 and newer. + * @param node + * the nodename. + * + * @param id + * an arbitrary number. + * + * @param serial + * another arbitrary number. + * + * @param creation + * yet another arbitrary number. + */ + protected OtpErlangPid(final int tag, final String node, final int id, + final int serial, final int creation) { + this.tag = tag; + this.node = node; + if (tag == OtpExternal.pidTag) { + this.id = id & 0x7fff; // 15 bits + this.serial = serial & 0x1fff; // 13 bits + this.creation = creation & 0x03; // 2 bits + } + else { // allow all 32 bits for newPidTag + this.id = id; + this.serial = serial; + this.creation = creation; + } + } + + protected int tag() { + return tag; } /** @@ -151,7 +191,7 @@ public class OtpErlangPid extends OtpErlangObject implements Comparable<Object> */ @Override public void encode(final OtpOutputStream buf) { - buf.write_pid(node, id, serial, creation); + buf.write_pid(this); } /** diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java index a6198d56cc..16c8d2ed85 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangPort.java @@ -26,6 +26,7 @@ public class OtpErlangPort extends OtpErlangObject { // don't change this! private static final long serialVersionUID = 4037115468007644704L; + private final int tag; private final String node; private final int id; private final int creation; @@ -42,6 +43,7 @@ public class OtpErlangPort extends OtpErlangObject { private OtpErlangPort(final OtpSelf self) { final OtpErlangPort p = self.createPort(); + tag = p.tag; id = p.id; creation = p.creation; node = p.node; @@ -62,6 +64,7 @@ public class OtpErlangPort extends OtpErlangObject { throws OtpErlangDecodeException { final OtpErlangPort p = buf.read_port(); + tag = p.tag; node = p.node(); id = p.id(); creation = p.creation(); @@ -77,13 +80,45 @@ public class OtpErlangPort extends OtpErlangObject { * an arbitrary number. Only the low order 28 bits will be used. * * @param creation - * another arbitrary number. Only the low order 2 bits will be - * used. + * another arbitrary number. Only the low order 2 bits will be used. */ public OtpErlangPort(final String node, final int id, final int creation) { - this.node = node; - this.id = id & 0xfffffff; // 28 bits - this.creation = creation & 0x03; // 2 bits + this(OtpExternal.portTag, node, id, creation); + } + + /** + * Create an Erlang port from its components. + * + * @param tag + * the external format to be compliant with. + * OtpExternal.portTag where only a subset of the bits are used (see other constructor) + * OtpExternal.newPortTag where all 32 bits of id and creation are significant. + * newPortTag can only be decoded by OTP-19 and newer. + * @param node + * the nodename. + * + * @param id + * an arbitrary number. Only the low order 28 bits will be used. + * + * @param creation + * another arbitrary number. + */ + public OtpErlangPort(final int tag, final String node, final int id, + final int creation) { + this.tag = tag; + this.node = node; + if (tag == OtpExternal.portTag) { + this.id = id & 0xfffffff; // 28 bits + this.creation = creation & 0x3; // 2 bits + } + else { + this.id = id; + this.creation = creation; + } + } + + protected int tag() { + return tag; } /** @@ -132,7 +167,7 @@ public class OtpErlangPort extends OtpErlangObject { */ @Override public void encode(final OtpOutputStream buf) { - buf.write_port(node, id, creation); + buf.write_port(this); } /** diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java index 8b57e7265b..c0a3a4061d 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpErlangRef.java @@ -28,11 +28,13 @@ public class OtpErlangRef extends OtpErlangObject { // don't change this! private static final long serialVersionUID = -7022666480768586521L; + private final int tag; private final String node; private final int creation; // old style refs have one 18-bit id // r6 "new" refs have array of ids, first one is only 18 bits however + // 19 "newer" refs have full 32-bits for creation and for ids[0] private int ids[] = null; /** @@ -47,6 +49,7 @@ public class OtpErlangRef extends OtpErlangObject { public OtpErlangRef(final OtpLocalNode self) { final OtpErlangRef r = self.createRef(); + tag = r.tag; ids = r.ids; creation = r.creation; node = r.node; @@ -67,6 +70,7 @@ public class OtpErlangRef extends OtpErlangObject { throws OtpErlangDecodeException { final OtpErlangRef r = buf.read_ref(); + tag = r.tag; node = r.node(); creation = r.creation(); @@ -83,10 +87,10 @@ public class OtpErlangRef extends OtpErlangObject { * an arbitrary number. Only the low order 18 bits will be used. * * @param creation - * another arbitrary number. Only the low order 2 bits will be - * used. + * another arbitrary number. */ public OtpErlangRef(final String node, final int id, final int creation) { + this.tag = OtpExternal.newRefTag; this.node = node; ids = new int[1]; ids[0] = id & 0x3ffff; // 18 bits @@ -110,10 +114,34 @@ public class OtpErlangRef extends OtpErlangObject { * used. */ public OtpErlangRef(final String node, final int[] ids, final int creation) { + this(OtpExternal.newRefTag, node, ids, creation); + } + + /** + * Create a new(er) style Erlang ref from its components. + * + * @param tag + * the external format to be compliant with. + * OtpExternal.newRefTag where only a subset of the bits are used (see other constructor) + * OtpExternal.newerRefTag where all bits of ids and creation are used. + * newerPortTag can only be decoded by OTP-19 and newer. + * + * @param node + * the nodename. + * + * @param ids + * an array of arbitrary numbers. At most three numbers + * will be read from the array. + * + * @param creation + * another arbitrary number. + */ + public OtpErlangRef(final int tag, final String node, final int[] ids, + final int creation) { + this.tag = tag; this.node = node; - this.creation = creation & 0x03; // 2 bits - // use at most 82 bits (18 + 32 + 32) + // use at most 3 words int len = ids.length; this.ids = new int[3]; this.ids[0] = 0; @@ -124,7 +152,17 @@ public class OtpErlangRef extends OtpErlangObject { len = 3; } System.arraycopy(ids, 0, this.ids, 0, len); - this.ids[0] &= 0x3ffff; // only 18 significant bits in first number + if (tag == OtpExternal.newRefTag) { + this.creation = creation & 0x3; + this.ids[0] &= 0x3ffff; // only 18 significant bits in first number + } + else { + this.creation = creation; + } + } + + protected int tag() { + return tag; } /** @@ -202,7 +240,7 @@ public class OtpErlangRef extends OtpErlangObject { */ @Override public void encode(final OtpOutputStream buf) { - buf.write_ref(node, ids, creation); + buf.write_ref(this); } /** diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpExternal.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpExternal.java index 4645f25590..e19e7304b7 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpExternal.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpExternal.java @@ -46,9 +46,11 @@ public class OtpExternal { /** The tag used for ports */ public static final int portTag = 102; + public static final int newPortTag = 89; /** The tag used for PIDs */ public static final int pidTag = 103; + public static final int newPidTag = 88; /** The tag used for small tuples */ public static final int smallTupleTag = 104; @@ -85,6 +87,7 @@ public class OtpExternal { /** The tag used for new style references */ public static final int newRefTag = 114; + public static final int newerRefTag = 90; /** The tag used for maps */ public static final int mapTag = 116; diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java index fa0815fbf0..50d825fb80 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpInputStream.java @@ -954,18 +954,23 @@ public class OtpInputStream extends ByteArrayInputStream { tag = read1skip_version(); - if (tag != OtpExternal.pidTag) { + if (tag != OtpExternal.pidTag && + tag != OtpExternal.newPidTag) { throw new OtpErlangDecodeException( "Wrong tag encountered, expected " + OtpExternal.pidTag + + " or " + OtpExternal.newPidTag + ", got " + tag); } node = read_atom(); - id = read4BE() & 0x7fff; // 15 bits - serial = read4BE() & 0x1fff; // 13 bits - creation = read1() & 0x03; // 2 bits - - return new OtpErlangPid(node, id, serial, creation); + id = read4BE(); + serial = read4BE(); + if (tag == OtpExternal.pidTag) + creation = read1(); + else + creation = read4BE(); + + return new OtpErlangPid(tag, node, id, serial, creation); } /** @@ -984,17 +989,22 @@ public class OtpInputStream extends ByteArrayInputStream { tag = read1skip_version(); - if (tag != OtpExternal.portTag) { + if (tag != OtpExternal.portTag && + tag != OtpExternal.newPortTag) { throw new OtpErlangDecodeException( "Wrong tag encountered, expected " + OtpExternal.portTag + + " or " + OtpExternal.newPortTag + ", got " + tag); } node = read_atom(); - id = read4BE() & 0xfffffff; // 28 bits - creation = read1() & 0x03; // 2 bits + id = read4BE(); + if (tag == OtpExternal.portTag) + creation = read1(); + else + creation = read4BE(); - return new OtpErlangPort(node, id, creation); + return new OtpErlangPort(tag, node, id, creation); } /** @@ -1021,16 +1031,23 @@ public class OtpInputStream extends ByteArrayInputStream { return new OtpErlangRef(node, id, creation); case OtpExternal.newRefTag: + case OtpExternal.newerRefTag: final int arity = read2BE(); + if (arity > 3) { + throw new OtpErlangDecodeException( + "Ref arity " + arity + " too large "); + } node = read_atom(); - creation = read1() & 0x03; // 2 bits + if (tag == OtpExternal.newRefTag) + creation = read1(); + else + creation = read4BE(); final int[] ids = new int[arity]; for (int i = 0; i < arity; i++) { ids[i] = read4BE(); } - ids[0] &= 0x3ffff; // first id gets truncated to 18 bits - return new OtpErlangRef(node, ids, creation); + return new OtpErlangRef(tag, node, ids, creation); default: throw new OtpErlangDecodeException( @@ -1200,15 +1217,18 @@ public class OtpInputStream extends ByteArrayInputStream { case OtpExternal.refTag: case OtpExternal.newRefTag: + case OtpExternal.newerRefTag: return new OtpErlangRef(this); case OtpExternal.mapTag: return new OtpErlangMap(this); case OtpExternal.portTag: + case OtpExternal.newPortTag: return new OtpErlangPort(this); case OtpExternal.pidTag: + case OtpExternal.newPidTag: return new OtpErlangPid(this); case OtpExternal.stringTag: diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java index 4faae2a157..10e48ffc43 100644 --- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java +++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpOutputStream.java @@ -728,14 +728,38 @@ public class OtpOutputStream extends ByteArrayOutputStream { */ public void write_pid(final String node, final int id, final int serial, final int creation) { - write1(OtpExternal.pidTag); - write_atom(node); - write4BE(id & 0x7fff); // 15 bits - write4BE(serial & 0x1fff); // 13 bits - write1(creation & 0x3); // 2 bits + write1(OtpExternal.pidTag); + write_atom(node); + write4BE(id & 0x7fff); // 15 bits + write4BE(serial & 0x1fff); // 13 bits + write1(creation & 0x3); // 2 bits } /** + * Write an Erlang PID to the stream. + * + * @param pid + * the pid + */ + public void write_pid(OtpErlangPid pid) { + write1(pid.tag()); + write_atom(pid.node()); + write4BE(pid.id()); + write4BE(pid.serial()); + switch (pid.tag()) { + case OtpExternal.pidTag: + write1(pid.creation()); + break; + case OtpExternal.newPidTag: + write4BE(pid.creation()); + break; + default: + throw new AssertionError("Invalid pid tag " + pid.tag()); + } + } + + + /** * Write an Erlang port to the stream. * * @param node @@ -745,15 +769,36 @@ public class OtpOutputStream extends ByteArrayOutputStream { * an arbitrary number. Only the low order 28 bits will be used. * * @param creation - * another arbitrary number. Only the low order 2 bits will be - * used. - * + * another arbitrary number. Only the low order 2 bits will + * be used. */ public void write_port(final String node, final int id, final int creation) { - write1(OtpExternal.portTag); - write_atom(node); - write4BE(id & 0xfffffff); // 28 bits - write1(creation & 0x3); // 2 bits + write1(OtpExternal.portTag); + write_atom(node); + write4BE(id & 0xfffffff); // 28 bits + write1(creation & 0x3); // 2 bits + } + + /** + * Write an Erlang port to the stream. + * + * @param port + * the port. + */ + public void write_port(OtpErlangPort port) { + write1(port.tag()); + write_atom(port.node()); + write4BE(port.id()); + switch (port.tag()) { + case OtpExternal.portTag: + write1(port.creation()); + break; + case OtpExternal.newPortTag: + write4BE(port.creation()); + break; + default: + throw new AssertionError("Invalid port tag " + port.tag()); + } } /** @@ -766,32 +811,31 @@ public class OtpOutputStream extends ByteArrayOutputStream { * an arbitrary number. Only the low order 18 bits will be used. * * @param creation - * another arbitrary number. Only the low order 2 bits will be - * used. + * another arbitrary number. * */ public void write_ref(final String node, final int id, final int creation) { - write1(OtpExternal.refTag); - write_atom(node); - write4BE(id & 0x3ffff); // 18 bits - write1(creation & 0x3); // 2 bits + /* Always encode as an extended reference; all + participating parties are now expected to be + able to decode extended references. */ + int ids[] = new int[1]; + ids[0] = id; + write_ref(node, ids, creation); } /** - * Write a new style (R6 and later) Erlang ref to the stream. + * Write an Erlang ref to the stream. * * @param node * the nodename. * * @param ids * an array of arbitrary numbers. Only the low order 18 bits of - * the first number will be used. If the array contains only one - * number, an old style ref will be written instead. At most - * three numbers will be read from the array. + * the first number will be used. At most three numbers + * will be read from the array. * * @param creation - * another arbitrary number. Only the low order 2 bits will be - * used. + * another arbitrary number. Only the low order 2 bits will be used. * */ public void write_ref(final String node, final int[] ids, final int creation) { @@ -800,29 +844,54 @@ public class OtpOutputStream extends ByteArrayOutputStream { arity = 3; // max 3 words in ref } - if (arity == 1) { - // use old method - this.write_ref(node, ids[0], creation); - } else { - // r6 ref - write1(OtpExternal.newRefTag); + write1(OtpExternal.newRefTag); - // how many id values - write2BE(arity); + // how many id values + write2BE(arity); - write_atom(node); + write_atom(node); - // note: creation BEFORE id in r6 ref - write1(creation & 0x3); // 2 bits + write1(creation & 0x3); // 2 bits - // first int gets truncated to 18 bits - write4BE(ids[0] & 0x3ffff); + // first int gets truncated to 18 bits + write4BE(ids[0] & 0x3ffff); - // remaining ones are left as is - for (int i = 1; i < arity; i++) { - write4BE(ids[i]); - } - } + // remaining ones are left as is + for (int i = 1; i < arity; i++) { + write4BE(ids[i]); + } + } + + /** + * Write an Erlang ref to the stream. + * + * @param ref + * the reference + */ + public void write_ref(OtpErlangRef ref) { + int[] ids = ref.ids(); + int arity = ids.length; + + write1(ref.tag()); + write2BE(arity); + write_atom(ref.node()); + + switch (ref.tag()) { + case OtpExternal.newRefTag: + write1(ref.creation()); + write4BE(ids[0] & 0x3ffff); // first word gets truncated to 18 bits + break; + case OtpExternal.newerRefTag: + write4BE(ref.creation()); + write4BE(ids[0]); // full first word + break; + default: + throw new AssertionError("Invalid ref tag " + ref.tag()); + } + + for (int i = 1; i < arity; i++) { + write4BE(ids[i]); + } } /** |