From dc449f160882fbd2cf268e5c50dd084dbe8b63a4 Mon Sep 17 00:00:00 2001 From: leventov Date: Sat, 6 Dec 2014 00:06:55 +0700 Subject: [PATCH 1/2] Check in Heap and Native generated impls of BondVOInterface for quicker reference --- .../map/fromdocs/BondVOInterface$$Heap.java | 174 +++++++++++++++ .../map/fromdocs/BondVOInterface$$Native.java | 203 ++++++++++++++++++ .../BondVOInterface$MarketPx$$Heap.java | 128 +++++++++++ .../BondVOInterface$MarketPx$$Native.java | 165 ++++++++++++++ 4 files changed, 670 insertions(+) create mode 100644 src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java create mode 100644 src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java create mode 100644 src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java create mode 100644 src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java new file mode 100644 index 000000000..3db5fc71a --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Heap.java @@ -0,0 +1,174 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.fromdocs; + +import static net.openhft.lang.Compare.*; +import java.io.IOException; +import net.openhft.chronicle.map.fromdocs.BondVOInterface; +import net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx; +import net.openhft.lang.io.Bytes; +import net.openhft.lang.io.serialization.BytesMarshallable; +import net.openhft.lang.model.Copyable; + +public class BondVOInterface$$Heap implements BondVOInterface, BytesMarshallable, Copyable { + private double _coupon; + private long _issueDate; + private long _maturityDate; + private int _entry; + private net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx[] _marketPxIntraDayHistory = new net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx[7]; + { + for (int i = 0; i < _marketPxIntraDayHistory.length; i++) + _marketPxIntraDayHistory[i] = new net.openhft.chronicle.map.fromdocs.BondVOInterface$MarketPx$$Heap(); + } private java.lang.String _symbol; + + public void setCoupon(double $) { + _coupon = $; + } + + public double getCoupon() { + return _coupon; + } + + public synchronized double addAtomicCoupon(double $) { + return _coupon += $; + } + + public synchronized boolean compareAndSwapCoupon(double _1, double _2) { + if (_coupon == _1) { + _coupon = _2; + return true; + } + return false; + } + public void setIssueDate(long $) { + _issueDate = $; + } + + public long getIssueDate() { + return _issueDate; + } + + public void setMaturityDate(long $) { + _maturityDate = $; + } + + public long getMaturityDate() { + return _maturityDate; + } + + public synchronized long addAtomicMaturityDate(long $) { + return _maturityDate += $; + } + + public void unlockEntry() { + throw new UnsupportedOperationException(); + } public void busyLockEntry() { + throw new UnsupportedOperationException(); + } public void setMarketPxIntraDayHistoryAt(int i, net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx $) { + if(i<0) throw new ArrayIndexOutOfBoundsException(i + " must be greater than 0"); + if(i>=7) throw new ArrayIndexOutOfBoundsException(i + " must be less than 7"); + _marketPxIntraDayHistory[i] = $; + } + + public net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx getMarketPxIntraDayHistoryAt(int i) { + if(i<0) throw new ArrayIndexOutOfBoundsException(i + " must be greater than 0"); + if(i>=7) throw new ArrayIndexOutOfBoundsException(i + " must be less than 7"); + return _marketPxIntraDayHistory[i]; + } + + public void setSymbol(java.lang.String $) { + _symbol = $; + } + + public java.lang.String getSymbol() { + return _symbol; + } + + @SuppressWarnings("unchecked") + public void copyFrom(net.openhft.chronicle.map.fromdocs.BondVOInterface from) { + setCoupon(from.getCoupon()); + setIssueDate(from.getIssueDate()); + setMaturityDate(from.getMaturityDate()); + for (int i = 0; i < 7; i++){ + setMarketPxIntraDayHistoryAt(i, from.getMarketPxIntraDayHistoryAt(i)); + } + setSymbol(from.getSymbol()); + } + + public void writeMarshallable(Bytes out) { + out.writeDouble(getCoupon()); + out.writeLong(getIssueDate()); + out.writeLong(getMaturityDate()); + for (int i = 0; i < 7; i++){ + out.writeObject(getMarketPxIntraDayHistoryAt(i)); + } + out.writeUTFΔ(getSymbol()); + } + public void readMarshallable(Bytes in) { + _coupon = in.readDouble(); + _issueDate = in.readLong(); + _maturityDate = in.readLong(); + _entry = in.readInt(); + for (int i = 0; i < 7; i++){ + _marketPxIntraDayHistory[i] = in.readObject(net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx.class); + } + _symbol = in.readUTFΔ(); + } + + public long longHashCode_marketPxIntraDayHistory() { + long hc = 0; + for (int i = 0; i < 7; i++) { + hc += calcLongHashCode(getMarketPxIntraDayHistoryAt(i)); + } + return hc; + } + + public int hashCode() { + long lhc = longHashCode(); + return (int) ((lhc >>> 32) ^ lhc); + } + + public long longHashCode() { + return ((((calcLongHashCode(getCoupon())) * 10191 + + calcLongHashCode(getIssueDate())) * 10191 + + calcLongHashCode(getMaturityDate())) * 10191 + + longHashCode_marketPxIntraDayHistory()) * 10191 + + calcLongHashCode(getSymbol()); + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BondVOInterface)) return false; + BondVOInterface that = (BondVOInterface) o; + + if(!isEqual(getCoupon(), that.getCoupon())) return false; + if(!isEqual(getIssueDate(), that.getIssueDate())) return false; + if(!isEqual(getMaturityDate(), that.getMaturityDate())) return false; + for (int i = 0; i <7; i++) { + if(!isEqual(getMarketPxIntraDayHistoryAt(i), that.getMarketPxIntraDayHistoryAt(i))) return false; + } + if(!isEqual(getSymbol(), that.getSymbol())) return false; + return true; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("BondVOInterface{ "); + sb.append(" }"); + return sb.toString(); + } +} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java new file mode 100644 index 000000000..6ab936a20 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$$Native.java @@ -0,0 +1,203 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.fromdocs; + + +import net.openhft.lang.io.Bytes; +import net.openhft.lang.io.serialization.BytesMarshallable; +import net.openhft.lang.model.Byteable; +import net.openhft.lang.model.Copyable; + +import static net.openhft.lang.Compare.calcLongHashCode; +import static net.openhft.lang.Compare.isEqual; + +public class BondVOInterface$$Native + implements BondVOInterface, BytesMarshallable, Byteable, + Copyable { + private static final int COUPON = 0; + private static final int ISSUEDATE = 8; + private static final int MATURITYDATE = 16; + private static final int ENTRY = 24; + private static final int MARKETPXINTRADAYHISTORY = 28; + private final BondVOInterface$MarketPx$$Native _marketPxIntraDayHistory[] = + new BondVOInterface$MarketPx$$Native[7]; + { + for (int i = 0; i < 7; i++) + _marketPxIntraDayHistory[i] = new BondVOInterface$MarketPx$$Native(); + } + private static final int SYMBOL = 308; + + + private Bytes _bytes; + private long _offset; + + + + public void setCoupon(double $) { + _bytes.writeDouble(_offset + COUPON, $); + } + + public double getCoupon() { + return _bytes.readDouble(_offset + COUPON); + } + + public double addAtomicCoupon(double $) { + return _bytes.addAtomicDouble(_offset + COUPON, $); + } public boolean compareAndSwapCoupon(double _1, double _2) { + return _bytes.compareAndSwapDouble(_offset + COUPON, _1, _2); + } + + public void setIssueDate(long $) { + _bytes.writeLong(_offset + ISSUEDATE, $); + } + + public long getIssueDate() { + return _bytes.readLong(_offset + ISSUEDATE); + } + + + + public void setMaturityDate(long $) { + _bytes.writeLong(_offset + MATURITYDATE, $); + } + + public long getMaturityDate() { + return _bytes.readLong(_offset + MATURITYDATE); + } + + public long addAtomicMaturityDate(long $) { + return _bytes.addAtomicLong(_offset + MATURITYDATE, $); + } public void unlockEntry() { + _bytes.unlockInt(_offset + ENTRY); + } public void busyLockEntry() throws InterruptedException { + _bytes.busyLockInt(_offset + ENTRY); + } public void setMarketPxIntraDayHistoryAt(int i, BondVOInterface.MarketPx $) { + _marketPxIntraDayHistory[i].copyFrom($); + } + + public BondVOInterface.MarketPx getMarketPxIntraDayHistoryAt(int i) { + return _marketPxIntraDayHistory[i]; + } + + + + public void setSymbol(java.lang.String $) { + _bytes.writeUTFΔ(_offset + SYMBOL, 20, $); + } + + public java.lang.String getSymbol() { + return _bytes.readUTFΔ(_offset + SYMBOL); + } + + @Override + public void copyFrom(BondVOInterface from) { + setCoupon(from.getCoupon()); + setIssueDate(from.getIssueDate()); + setMaturityDate(from.getMaturityDate()); + for (int i = 0; i < 7; i++){ + setMarketPxIntraDayHistoryAt(i, from.getMarketPxIntraDayHistoryAt(i)); + } + setSymbol(from.getSymbol()); + } + + @Override + public void writeMarshallable(Bytes out) { + out.writeDouble(getCoupon()); + out.writeLong(getIssueDate()); + out.writeLong(getMaturityDate()); + for (int i = 0; i < 7; i++){ + _marketPxIntraDayHistory[i].writeMarshallable(out); + } + out.writeUTFΔ(getSymbol()); + } + @Override + public void readMarshallable(Bytes in) { + setCoupon(in.readDouble()); + setIssueDate(in.readLong()); + setMaturityDate(in.readLong()); + for (int i = 0; i < 7; i++){ + _marketPxIntraDayHistory[i].readMarshallable(in); + } + setSymbol(in.readUTFΔ()); + } + @Override + public void bytes(Bytes bytes, long offset) { + this._bytes = bytes; + this._offset = offset; + for (int i = 0; i < 7; i++){ + ((Byteable) _marketPxIntraDayHistory[i]).bytes(bytes, + _offset + MARKETPXINTRADAYHISTORY + (i * 40)); + } + } + @Override + public Bytes bytes() { + return _bytes; + } + @Override + public long offset() { + return _offset; + } + @Override + public int maxSize() { + return 328; + } + + public long longHashCode_marketPxIntraDayHistory() { + long hc = 0; + for (int i = 0; i < 7; i++) { + hc += calcLongHashCode(getMarketPxIntraDayHistoryAt(i)); + } + return hc; + } + + public int hashCode() { + long lhc = longHashCode(); + return (int) ((lhc >>> 32) ^ lhc); + } + + public long longHashCode() { + return ((((calcLongHashCode(getCoupon())) * 10191 + + calcLongHashCode(getIssueDate())) * 10191 + + calcLongHashCode(getMaturityDate())) * 10191 + + longHashCode_marketPxIntraDayHistory()) * 10191 + + calcLongHashCode(getSymbol()); + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BondVOInterface)) return false; + BondVOInterface that = (BondVOInterface) o; + + if(!isEqual(getCoupon(), that.getCoupon())) return false; + if(!isEqual(getIssueDate(), that.getIssueDate())) return false; + if(!isEqual(getMaturityDate(), that.getMaturityDate())) return false; + for (int i = 0; i <7; i++) { + if(!isEqual(getMarketPxIntraDayHistoryAt(i), that.getMarketPxIntraDayHistoryAt(i))) + return false; + } + if(!isEqual(getSymbol(), that.getSymbol())) return false; + return true; + } + + public String toString() { + if (_bytes == null) return "bytes is null"; + StringBuilder sb = new StringBuilder(); + sb.append("BondVOInterface{ "); + sb.append(" }"); + return sb.toString(); + } +} diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java new file mode 100644 index 000000000..cd7839302 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Heap.java @@ -0,0 +1,128 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.fromdocs; + +import static net.openhft.lang.Compare.*; +import java.io.IOException; +import net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx; +import net.openhft.lang.io.Bytes; +import net.openhft.lang.io.serialization.BytesMarshallable; +import net.openhft.lang.model.Copyable; + +public class BondVOInterface$MarketPx$$Heap implements MarketPx, BytesMarshallable, Copyable { + private double _askPx; + private double _bidPx; + private double _callPx; + private double _maturityPx; + private double _parPx; + + public void setAskPx(double $) { + _askPx = $; + } + + public double getAskPx() { + return _askPx; + } + + public void setBidPx(double $) { + _bidPx = $; + } + + public double getBidPx() { + return _bidPx; + } + + public void setCallPx(double $) { + _callPx = $; + } + + public double getCallPx() { + return _callPx; + } + + public void setMaturityPx(double $) { + _maturityPx = $; + } + + public double getMaturityPx() { + return _maturityPx; + } + + public void setParPx(double $) { + _parPx = $; + } + + public double getParPx() { + return _parPx; + } + + @SuppressWarnings("unchecked") + public void copyFrom(net.openhft.chronicle.map.fromdocs.BondVOInterface.MarketPx from) { + setAskPx(from.getAskPx()); + setBidPx(from.getBidPx()); + setCallPx(from.getCallPx()); + setMaturityPx(from.getMaturityPx()); + setParPx(from.getParPx()); + } + + public void writeMarshallable(Bytes out) { + out.writeDouble(getAskPx()); + out.writeDouble(getBidPx()); + out.writeDouble(getCallPx()); + out.writeDouble(getMaturityPx()); + out.writeDouble(getParPx()); + } + public void readMarshallable(Bytes in) { + _askPx = in.readDouble(); + _bidPx = in.readDouble(); + _callPx = in.readDouble(); + _maturityPx = in.readDouble(); + _parPx = in.readDouble(); + } + public int hashCode() { + long lhc = longHashCode(); + return (int) ((lhc >>> 32) ^ lhc); + } + + public long longHashCode() { + return ((((calcLongHashCode(getAskPx())) * 10191 + + calcLongHashCode(getBidPx())) * 10191 + + calcLongHashCode(getCallPx())) * 10191 + + calcLongHashCode(getMaturityPx())) * 10191 + + calcLongHashCode(getParPx()); + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BondVOInterface.MarketPx)) return false; + BondVOInterface.MarketPx that = (BondVOInterface.MarketPx) o; + + if(!isEqual(getAskPx(), that.getAskPx())) return false; + if(!isEqual(getBidPx(), that.getBidPx())) return false; + if(!isEqual(getCallPx(), that.getCallPx())) return false; + if(!isEqual(getMaturityPx(), that.getMaturityPx())) return false; + if(!isEqual(getParPx(), that.getParPx())) return false; + return true; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("BondVOInterface.MarketPx{ "); + sb.append(" }"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java new file mode 100644 index 000000000..67aa52ba0 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/fromdocs/BondVOInterface$MarketPx$$Native.java @@ -0,0 +1,165 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map.fromdocs; + +import net.openhft.lang.io.Bytes; +import net.openhft.lang.io.serialization.BytesMarshallable; +import net.openhft.lang.model.Byteable; +import net.openhft.lang.model.Copyable; + +import static net.openhft.lang.Compare.calcLongHashCode; +import static net.openhft.lang.Compare.isEqual; + +public class BondVOInterface$MarketPx$$Native + implements BondVOInterface.MarketPx, BytesMarshallable, Byteable, + Copyable { + private static final int ASKPX = 0; + private static final int BIDPX = 8; + private static final int CALLPX = 16; + private static final int MATURITYPX = 24; + private static final int PARPX = 32; + + + private Bytes _bytes; + private long _offset; + + + + public void setAskPx(double $) { + _bytes.writeDouble(_offset + ASKPX, $); + } + + public double getAskPx() { + return _bytes.readDouble(_offset + ASKPX); + } + + + + public void setBidPx(double $) { + _bytes.writeDouble(_offset + BIDPX, $); + } + + public double getBidPx() { + return _bytes.readDouble(_offset + BIDPX); + } + + + + public void setCallPx(double $) { + _bytes.writeDouble(_offset + CALLPX, $); + } + + public double getCallPx() { + return _bytes.readDouble(_offset + CALLPX); + } + + + + public void setMaturityPx(double $) { + _bytes.writeDouble(_offset + MATURITYPX, $); + } + + public double getMaturityPx() { + return _bytes.readDouble(_offset + MATURITYPX); + } + + + + public void setParPx(double $) { + _bytes.writeDouble(_offset + PARPX, $); + } + + public double getParPx() { + return _bytes.readDouble(_offset + PARPX); + } + + @Override + public void copyFrom(BondVOInterface.MarketPx from) { + setAskPx(from.getAskPx()); + setBidPx(from.getBidPx()); + setCallPx(from.getCallPx()); + setMaturityPx(from.getMaturityPx()); + setParPx(from.getParPx()); + } + + @Override + public void writeMarshallable(Bytes out) { + out.writeDouble(getAskPx()); + out.writeDouble(getBidPx()); + out.writeDouble(getCallPx()); + out.writeDouble(getMaturityPx()); + out.writeDouble(getParPx()); + } + @Override + public void readMarshallable(Bytes in) { + setAskPx(in.readDouble()); + setBidPx(in.readDouble()); + setCallPx(in.readDouble()); + setMaturityPx(in.readDouble()); + setParPx(in.readDouble()); + } + @Override + public void bytes(Bytes bytes, long offset) { + this._bytes = bytes; + this._offset = offset; + } + @Override + public Bytes bytes() { + return _bytes; + } + @Override + public long offset() { + return _offset; + } + @Override + public int maxSize() { + return 40; + } + public int hashCode() { + long lhc = longHashCode(); + return (int) ((lhc >>> 32) ^ lhc); + } + + public long longHashCode() { + return ((((calcLongHashCode(getAskPx())) * 10191 + + calcLongHashCode(getBidPx())) * 10191 + + calcLongHashCode(getCallPx())) * 10191 + + calcLongHashCode(getMaturityPx())) * 10191 + + calcLongHashCode(getParPx()); + } + + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BondVOInterface.MarketPx)) return false; + BondVOInterface.MarketPx that = (BondVOInterface.MarketPx) o; + + if(!isEqual(getAskPx(), that.getAskPx())) return false; + if(!isEqual(getBidPx(), that.getBidPx())) return false; + if(!isEqual(getCallPx(), that.getCallPx())) return false; + if(!isEqual(getMaturityPx(), that.getMaturityPx())) return false; + if(!isEqual(getParPx(), that.getParPx())) return false; + return true; + } + + public String toString() { + if (_bytes == null) return "bytes is null"; + StringBuilder sb = new StringBuilder(); + sb.append("BondVOInterface.MarketPx{ "); + sb.append(" }"); + return sb.toString(); + } +} From f8cb1d49d9db7c405c5f3edf5a41c30d5d5d12f5 Mon Sep 17 00:00:00 2001 From: leventov Date: Sat, 6 Dec 2014 00:09:50 +0700 Subject: [PATCH 2/2] JLANG-39 implemented universal readers/writers for classes eligible for dataValue generation, test of the simplier case --- .../internal/DataValueBytesMarshallers.java | 481 ++++++++++++++++++ .../map/AbstractChronicleMapBuilder.java | 2 - .../chronicle/map/SerializationBuilder.java | 32 +- src/test/java/eg/BGChronicleTest.java | 6 +- .../chronicle/map/DataKeyValueTest.java | 56 ++ 5 files changed, 572 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java create mode 100644 src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java diff --git a/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java new file mode 100644 index 000000000..0e71de34d --- /dev/null +++ b/src/main/java/net/openhft/chronicle/hash/serialization/internal/DataValueBytesMarshallers.java @@ -0,0 +1,481 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.hash.serialization.internal; + +import net.openhft.chronicle.hash.serialization.BytesReader; +import net.openhft.chronicle.hash.serialization.BytesWriter; +import net.openhft.compiler.CompilerUtils; +import net.openhft.lang.io.Bytes; +import net.openhft.lang.io.serialization.ObjectFactory; +import net.openhft.lang.model.*; +import org.jetbrains.annotations.NotNull; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.SortedSet; +import java.util.concurrent.ConcurrentHashMap; + +import static net.openhft.lang.model.DataValueGenerator.*; + +public final class DataValueBytesMarshallers { + + private static final boolean dumpCode = Boolean.getBoolean("dvg.dumpCode"); + private static final Map readersClassMap = + new ConcurrentHashMap<>(); + private static final Map readersWithCustomFactoriesClassMap = + new ConcurrentHashMap<>(); + private static final Map writerClassMap = + new ConcurrentHashMap<>(); + + public static BytesReader acquireBytesReader(Class tClass) { + Class readerClass = acquireReaderClass(tClass); + try { + Field instanceField = readerClass.getDeclaredField("INSTANCE"); + Object reader = instanceField.get(null); + return (BytesReader) reader; + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new AssertionError(e); + } + } + + public static BytesReader acquireBytesReader(Class tClass, ObjectFactory factory) { + Class readerClass = acquireReaderWithCustomFactory(tClass); + try { + Constructor constructor = readerClass.getConstructor(ObjectFactory.class); + Object reader = constructor.newInstance(factory); + return (BytesReader) reader; + } catch (IllegalAccessException | NoSuchMethodException | InstantiationException | + InvocationTargetException e) { + throw new AssertionError(e); + } + } + + public static BytesWriter acquireBytesWriter(Class tClass) { + Class readerClass = acquireWriterClass(tClass); + try { + Field instanceField = readerClass.getDeclaredField("INSTANCE"); + Object reader = instanceField.get(null); + return (BytesWriter) reader; + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new AssertionError(e); + } + } + + + public static Class acquireReaderClass(Class tClass) { + DataValueClasses.directClassFor(tClass); + Class readerClass = readersClassMap.get(tClass); + if (readerClass != null) + return readerClass; + DataValueModel dvmodel = DataValueModels.acquireModel(tClass); + for (Class clazz : dvmodel.nestedModels()) { + // touch them to make sure they are loaded. + Class clazz2 = acquireReaderClass(clazz); + } + String actual = generateBytesReader(tClass); + if (dumpCode) + LoggerFactory.getLogger(DataValueGenerator.class).info(actual); + ClassLoader classLoader = tClass.getClassLoader(); + String className = bytesReaderName(tClass, false); + try { + readerClass = classLoader.loadClass(className); + } catch (ClassNotFoundException ignored) { + try { + readerClass = CompilerUtils.CACHED_COMPILER + .loadFromJava(classLoader, className, actual); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + readersClassMap.put(tClass, readerClass); + return readerClass; + } + + public static Class acquireWriterClass(Class tClass) { + Class writerClass = writerClassMap.get(tClass); + if (writerClass != null) + return writerClass; + DataValueModel dvmodel = DataValueModels.acquireModel(tClass); + for (Class clazz : dvmodel.nestedModels()) { + // touch them to make sure they are loaded. + Class clazz2 = acquireWriterClass(clazz); + } + String actual = generateBytesWriter(tClass); + if (dumpCode) + LoggerFactory.getLogger(DataValueGenerator.class).info(actual); + ClassLoader classLoader = tClass.getClassLoader(); + String className = bytesWriterName(tClass, false); + try { + writerClass = classLoader.loadClass(className); + } catch (ClassNotFoundException ignored) { + try { + writerClass = CompilerUtils.CACHED_COMPILER + .loadFromJava(classLoader, className, actual); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + writerClassMap.put(tClass, writerClass); + return writerClass; + } + + public static Class acquireReaderWithCustomFactory(Class tClass) { + Class c = readersWithCustomFactoriesClassMap.get(tClass); + if (c != null) + return c; + acquireReaderClass(tClass); + String actual = generateWithCustomFactoryClass(tClass); + if (dumpCode) + LoggerFactory.getLogger(DataValueGenerator.class).info(actual); + ClassLoader classLoader = tClass.getClassLoader(); + String className = bytesReaderName(tClass, false) + "$WithCustomFactory"; + try { + c = classLoader.loadClass(className); + } catch (ClassNotFoundException ignored) { + try { + c = CompilerUtils.CACHED_COMPILER + .loadFromJava(classLoader, className, actual); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + readersWithCustomFactoriesClassMap.put(tClass, c); + return c; + } + + private static String generateWithCustomFactoryClass(Class tClass) { + DataValueModel dvModel = DataValueModels.acquireModel(tClass); + + SortedSet imported = newImported(); + imported.add(ObjectFactory.class); + imported.add(NotNull.class); + imported.add(dvModel.type()); + + String simpleName = tClass.getSimpleName(); + + String bytesReaderName = bytesReaderName(simpleName(tClass)); + String name = bytesReaderName + "$WithCustomFactory"; + String withCustomFactoryClass = + "public final class " + name + " extends " + bytesReaderName + " {\n" + + " private static final long serialVersionUID = 0L;\n" + + "\n" + + " @NotNull\n" + + " private final ObjectFactory<" + simpleName + "> factory;\n" + + "\n" + + " " + name + "(@NotNull ObjectFactory<" + + simpleName + "> factory) {\n" + + " this.factory = factory;\n" + + " }\n" + + "\n" + + " @Override\n" + + " " + simpleName + " getInstance() throws Exception {\n" + + " return factory.create();\n" + + " }\n" + + "}\n"; + + StringBuilder sb = new StringBuilder(); + appendPackage(dvModel, sb); + appendImported(imported, sb); + sb.append(withCustomFactoryClass); + return sb.toString(); + } + + + + private static String bytesReaderName(Class type, boolean simple) { + return (simple ? type.getSimpleName() : type.getName()) + "$$BytesReader"; + } + + private static String bytesReaderName(String className) { + return className + "$$BytesReader"; + } + + public static String bytesWriterName(Class type, boolean simple) { + return (simple ? simpleName(type) : type.getName()) + "$$BytesWriter"; + } + + private static String generateBytesReader(Class tClass) { + DataValueModel dvModel = DataValueModels.acquireModel(tClass); + + SortedSet imported = newImported(); + imported.add(BytesReader.class); + imported.add(Bytes.class); + imported.add(ByteableMarshaller.class); + imported.add(Byteable.class); + imported.add(dvModel.type()); + + StringBuilder read = generateReadBody(dvModel, imported); + + StringBuilder sb = new StringBuilder(); + appendPackage(dvModel, sb); + appendImported(imported, sb); + String simpleName = tClass.getSimpleName(); + String bytesReaderName = bytesReaderName(tClass, false); + String simpleReaderName = bytesReaderName(simpleName(tClass)); + sb.append("\npublic class ").append(simpleReaderName) + .append(" implements BytesReader<").append(simpleName).append("> {\n"); + declareSerialVersionUID(sb); + declareStaticInstance(sb, tClass); + generatePrivateConstructor(sb, simpleReaderName); + generateGetInstance(sb, tClass); + generateDelegatingRead(sb, simpleName); + generateRead(read, sb, simpleName, tClass); + sb.append("}\n"); + return sb.toString(); + } + + private static StringBuilder generateReadBody(DataValueModel dvModel, + SortedSet imported) { + StringBuilder read = new StringBuilder(); + + Map.Entry[] entries = + heapSizeOrderedFields(dvModel); + for (Map.Entry entry : entries) { + String name = entry.getKey(); + FieldModel model = entry.getValue(); + Class type = model.type(); + if (shouldImport(type)) + imported.add(type); + + Method setter = getSetter(model); + Method getter = getGetter(model); + + Method orderedSetter = getOrderedSetter(model); + Method volatileGetter = getVolatileGetter(model); + + Method defaultSetter = setter != null ? setter : orderedSetter; + Method defaultGetter = getter != null ? getter : volatileGetter; + if (!dvModel.isScalar(type)) { + if (model.isArray()) { + read.append(" for (int i = 0; i < ") + .append(model.indexSize().value()).append("; i++) {\n"); + read.append(" toReuse.") + .append(defaultSetter.getName()).append("(i, ") + .append(bytesReaderName(type, false)) + .append(".INSTANCE").append(".read(bytes, ") + .append(computeNonScalarOffset(dvModel, type)).append(", ") + .append(defaultGetter.getName()).append("(i)));"); + read.append(" }\n"); + } else { + read.append(" toReuse.") + .append(defaultSetter.getName()).append("(") + .append(bytesReaderName(type, false)) + .append(".INSTANCE").append(".read(bytes, ") + .append(computeNonScalarOffset(dvModel, type)).append(", ") + .append(defaultGetter.getName()).append("()));"); + } + } else { + if (model.isArray()) { + read.append(" for (int i = 0; i < ") + .append(model.indexSize().value()).append("; i++) {\n"); + read.append(" toReuse.").append(defaultSetter.getName()) + .append("(i, bytes.read").append(bytesType(type)).append("());\n"); + read.append(" }\n"); + } else { + read.append(" toReuse.").append(defaultSetter.getName()) + .append("(bytes.read").append(bytesType(type)).append("());\n"); + } + } + } + return read; + } + + private static String generateBytesWriter(Class tClass) { + DataValueModel dvModel = DataValueModels.acquireModel(tClass); + + SortedSet imported = newImported(); + imported.add(BytesWriter.class); + imported.add(Bytes.class); + imported.add(Byteable.class); + imported.add(dvModel.type()); + + String write = generateWriteBody(dvModel, imported); + + StringBuilder sb = new StringBuilder(); + appendPackage(dvModel, sb); + appendImported(imported, sb); + sb.append("public enum ").append(bytesWriterName(tClass, true)) + .append(" implements BytesWriter<").append(tClass.getSimpleName()).append("> {\n"); + sb.append(" INSTANCE;\n\n"); + generateSize(tClass, dvModel, sb); + generateWrite(tClass, dvModel, write, sb); + generateShouldNotBeNull(tClass, sb); + sb.append("}\n"); + return sb.toString(); + } + + private static void generateShouldNotBeNull(Class tClass, StringBuilder sb) { + sb.append(" private static void shouldNotBeNull() {\n"); + sb.append(" throw new NullPointerException(\"Sub-members of " + + tClass.getSimpleName() + " shouldn't be null for this writer. You should specify" + + " custom writer (e. g. using keyMarshallers()/valueMarshallers() methods of" + + "ChronicleMapBuilder, if you want to support null fields/array elements.\");\n"); + sb.append(" }\n"); + } + + private static void generateWrite(Class tClass, DataValueModel dvModel, String write, + StringBuilder sb) { + appendOverride(sb); + sb.append(" public void write(Bytes bytes, ") + .append(tClass.getSimpleName()).append(" e) {\n"); + int size = computeNonScalarOffset(dvModel, tClass); + if (size > 16) { + sb.append(" if (e instanceof Byteable) {\n"); + sb.append( + " Bytes eBytes = ((Byteable) e).bytes();\n" + + " if (eBytes != null) {\n" + + " bytes.write(eBytes, ((Byteable) e).offset(), " + + size + ");\n" + + " } else {\n" + + " throw new NullPointerException(" + + "\"You are trying to write a byteable object of \" +\n" + + " e.getClass() + \", \" +\n" + + " \"which bytes are not assigned. I. e. most likely " + + "the object is uninitialized.\");\n" + + " }\n"); + sb.append(" return;\n"); + sb.append(" }\n"); + } + sb.append(write); + sb.append(" }\n\n"); + } + + private static void generateSize(Class tClass, DataValueModel dvModel, StringBuilder sb) { + appendOverride(sb); + sb.append(" public long size(").append(tClass.getSimpleName()).append(" e) {\n"); + sb.append(" return ").append(computeNonScalarOffset(dvModel, tClass)).append(";\n"); + sb.append(" }\n\n"); + } + + private static String generateWriteBody(DataValueModel dvModel, SortedSet imported) { + StringBuilder write = new StringBuilder(); + + Map.Entry[] entries = + heapSizeOrderedFields(dvModel); + for (Map.Entry entry : entries) { + String name = entry.getKey(); + FieldModel model = entry.getValue(); + Class type = model.type(); + if (shouldImport(type)) + imported.add(type); + + Method setter = getSetter(model); + Method getter = getGetter(model); + + Method orderedSetter = getOrderedSetter(model); + Method volatileGetter = getVolatileGetter(model); + + Method defaultSetter = setter != null ? setter : orderedSetter; + Method defaultGetter = getter != null ? getter : volatileGetter; + if (!dvModel.isScalar(type)) { + if (model.isArray()) { + write.append(" for (int i = 0; i < ") + .append(model.indexSize().value()).append("; i++) {\n"); + write.append(" ") + .append(type.getName()).append(" ").append(" $ = e.") + .append(defaultGetter.getName()).append("(i);\n"); + write.append(" ") + .append("if ($ == null) shouldNotBeNull();\n"); + write.append(" ") + .append(bytesWriterName(type, false)) + .append(".INSTANCE").append(".write(bytes, $);\n"); + write.append(" }\n"); + } else { + write.append(" {") + .append(type.getName()).append(" ").append(" $ = e.") + .append(defaultGetter.getName()).append("();\n"); + write.append(" ") + .append("if ($ == null) shouldNotBeNull();\n"); + write.append(" ") + .append(bytesWriterName(type, false)) + .append(".INSTANCE").append(".write(bytes, $);}\n"); + } + } else { + if (model.isArray()) { + write.append(" for (int i = 0; i < ") + .append(model.indexSize().value()).append("; i++) {\n"); + write.append(" bytes.write").append(bytesType(type)) + .append("(e.").append(defaultGetter.getName()).append("(i));\n"); + write.append(" }\n"); + } else { + write.append(" bytes.write").append(bytesType(type)) + .append("(e.").append(defaultGetter.getName()).append("());\n"); + } + } + } + return write.toString(); + } + + private static void generateRead(StringBuilder read, StringBuilder sb, String simpleName, + Class cl) { + appendOverride(sb); + sb.append(" public ").append(simpleName).append(" read(Bytes bytes, long size, ") + .append(simpleName).append(" toReuse) {\n"); + sb.append(" try {\n"); + sb.append(" if (toReuse == null)\n"); + sb.append(" toReuse = getInstance();\n"); + sb.append(" if (toReuse instanceof Byteable && ") + .append("((Byteable) toReuse).bytes() == null) {\n"); + sb.append(" " + + "ByteableMarshaller.setBytesAndOffset(((Byteable) toReuse), bytes);\n"); + sb.append(" bytes.skip(size);\n"); + sb.append(" return toReuse;\n"); + sb.append(" }\n"); + sb.append(read); + sb.append(" return toReuse;\n"); + sb.append(" } catch (Exception e) {\n"); + sb.append(" throw new IllegalStateException(e);\n"); + sb.append(" }\n"); + sb.append("}\n\n"); + } + + private static void generateDelegatingRead(StringBuilder sb, String simpleName) { + appendOverride(sb); + sb.append(" public ").append(simpleName).append(" read(Bytes bytes, long size) {\n"); + sb.append(" return read(bytes, size, null);\n"); + sb.append(" }\n\n"); + } + + private static void appendOverride(StringBuilder sb) { + sb.append(" @Override\n"); + } + + private static void generatePrivateConstructor(StringBuilder sb, String bytesReaderName) { + sb.append(" ").append(bytesReaderName).append("() {}\n\n"); + } + + private static void declareStaticInstance(StringBuilder sb, Class cl) { + String bytesReaderName = bytesReaderName(simpleName(cl)); + sb.append(" public static final ").append(bytesReaderName).append(" INSTANCE = new ") + .append(bytesReaderName).append("();\n\n"); + } + + private static StringBuilder declareSerialVersionUID(StringBuilder sb) { + return sb.append(" private static final long serialVersionUID = 0L;\n\n"); + } + + private static void generateGetInstance(StringBuilder sb, Class cl) { + sb.append(" ").append(cl.getCanonicalName()) + .append(" getInstance() throws Exception {\n"); + sb.append(" ").append("return new ").append(cl.getName()).append("$$Native();\n"); + sb.append(" ").append("}\n\n"); + } +} diff --git a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java index d3bffe682..a9eb45115 100755 --- a/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/AbstractChronicleMapBuilder.java @@ -148,8 +148,6 @@ abstract class AbstractChronicleMapBuilder keyClass, Class valueClass) { keyBuilder = new SerializationBuilder(keyClass, SerializationBuilder.Role.KEY); valueBuilder = new SerializationBuilder(valueClass, SerializationBuilder.Role.VALUE); - if (valueClass == LongValue.class) - prepareValueBytesOnAcquire(new ZeroOutValueBytes(valueSize())); } protected static boolean offHeapReference(Class valueClass) { diff --git a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java index 4f34d14f4..fb4be52d4 100644 --- a/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java +++ b/src/main/java/net/openhft/chronicle/map/SerializationBuilder.java @@ -18,6 +18,7 @@ package net.openhft.chronicle.map; +import net.openhft.lang.model.*; import net.openhft.lang.threadlocal.Provider; import net.openhft.lang.threadlocal.ThreadLocalCopies; import net.openhft.chronicle.hash.serialization.*; @@ -28,7 +29,6 @@ import net.openhft.lang.io.serialization.BytesMarshaller; import net.openhft.lang.io.serialization.ObjectFactory; import net.openhft.lang.io.serialization.ObjectSerializer; import net.openhft.lang.io.serialization.impl.*; -import net.openhft.lang.model.Byteable; import net.openhft.lang.values.LongValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,6 +38,7 @@ import java.io.IOException; import java.io.Serializable; import java.lang.reflect.Modifier; +import static net.openhft.chronicle.hash.serialization.SizeMarshallers.constant; import static net.openhft.chronicle.map.Objects.hash; import static net.openhft.chronicle.hash.serialization.SizeMarshallers.stopBit; import static net.openhft.chronicle.map.SerializationBuilder.Role.KEY; @@ -65,6 +66,7 @@ final class SerializationBuilder implements Cloneable, Serializable{ private final Role role; final Class eClass; private boolean instancesAreMutable; + private boolean dataValueClass = false; private SizeMarshaller sizeMarshaller = stopBit(); private BytesReader reader; private Object interop; @@ -83,6 +85,22 @@ final class SerializationBuilder implements Cloneable, Serializable{ new NewInstanceObjectFactory(eClass) : NullObjectFactory.of(); + if (eClass.isInterface()) { + try { + BytesReader reader = DataValueBytesMarshallers.acquireBytesReader(eClass); + BytesWriter writer = DataValueBytesMarshallers.acquireBytesWriter(eClass); + DataValueModel model = DataValueModels.acquireModel(eClass); + int size = DataValueGenerator.computeNonScalarOffset(model, eClass); + dataValueClass = true; + reader(reader); + writer(writer); + sizeMarshaller(constant((long) size)); + return; + } catch (Exception e) { + // ignore, fall through + } + } + if (concreteClass(eClass) && Byteable.class.isAssignableFrom(eClass)) { ByteableMarshaller byteableMarshaller = ByteableMarshaller.of((Class) eClass); sizeMarshaller(byteableMarshaller); @@ -129,6 +147,10 @@ final class SerializationBuilder implements Cloneable, Serializable{ } } + private void clearDefaults() { + dataValueClass = false; + } + @SuppressWarnings("unchecked") private BytesMarshaller chooseMarshaller(Class eClass, Class classForMarshaller) { if (BytesMarshallable.class.isAssignableFrom(eClass)) @@ -144,6 +166,7 @@ final class SerializationBuilder implements Cloneable, Serializable{ } public SerializationBuilder interop(BytesInterop interop) { + clearDefaults(); return copyingInterop(null) .setInterop(interop) .metaInterop(DelegatingMetaBytesInterop.>instance()) @@ -152,6 +175,7 @@ final class SerializationBuilder implements Cloneable, Serializable{ } public SerializationBuilder writer(BytesWriter writer) { + clearDefaults(); if (writer instanceof BytesInterop) return interop((BytesInterop) writer); return copyingInterop(CopyingInterop.FROM_WRITER) @@ -161,6 +185,7 @@ final class SerializationBuilder implements Cloneable, Serializable{ } public SerializationBuilder marshaller(BytesMarshaller marshaller) { + clearDefaults(); return copyingInterop(CopyingInterop.FROM_MARSHALLER) .reader(BytesReaders.fromBytesMarshaller(marshaller)) .setInterop(marshaller) @@ -247,6 +272,7 @@ final class SerializationBuilder implements Cloneable, Serializable{ } public SerializationBuilder reader(BytesReader reader) { + clearDefaults(); this.reader = reader; return this; } @@ -282,6 +308,10 @@ final class SerializationBuilder implements Cloneable, Serializable{ @SuppressWarnings("unchecked") public SerializationBuilder factory(ObjectFactory factory) { + if (dataValueClass) { + reader(DataValueBytesMarshallers.acquireBytesReader(eClass, factory)); + return this; + } if (!marshallerUseFactory(eClass)) { throw new IllegalStateException("Default marshaller for " + eClass + " value don't use object factory"); diff --git a/src/test/java/eg/BGChronicleTest.java b/src/test/java/eg/BGChronicleTest.java index df831891b..a489cd0de 100644 --- a/src/test/java/eg/BGChronicleTest.java +++ b/src/test/java/eg/BGChronicleTest.java @@ -22,7 +22,8 @@ public class BGChronicleTest { byte[] value = new byte[11]; - public ChronicleMap startChronicleMapServer(int port) throws InterruptedException, IOException { + public ChronicleMap startChronicleMapServer(int port) + throws InterruptedException, IOException { TcpTransportAndNetworkConfig serverConfig = TcpTransportAndNetworkConfig.of(port) @@ -107,7 +108,8 @@ public class BGChronicleTest { final InetSocketAddress serverHostPort = new InetSocketAddress(hostNameOrIpAddress, port); - TcpTransportAndNetworkConfig clientConfig = TcpTransportAndNetworkConfig.of(port + 1, serverHostPort) + TcpTransportAndNetworkConfig clientConfig = + TcpTransportAndNetworkConfig.of(port + 1, serverHostPort) .heartBeatInterval(CHRONICLE_HEARTBEAT_SECONDS, TimeUnit.SECONDS).name("clientMap") .autoReconnectedUponDroppedConnection(true); diff --git a/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java b/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java new file mode 100644 index 000000000..7d2cb72e1 --- /dev/null +++ b/src/test/java/net/openhft/chronicle/map/DataKeyValueTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2014 Higher Frequency Trading http://www.higherfrequencytrading.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.openhft.chronicle.map; + +import net.openhft.lang.model.Byteable; +import net.openhft.lang.model.DataValueClasses; +import net.openhft.lang.values.IntValue; +import net.openhft.lang.values.LongValue; +import org.junit.Assert; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class DataKeyValueTest { + + @Test + public void dataKeyValueTest() { + ChronicleMap map = + OnHeapUpdatableChronicleMapBuilder.of(IntValue.class, LongValue.class) + .entries(1000).create(); + IntValue heapKey = DataValueClasses.newInstance(IntValue.class); + IntValue directKey = DataValueClasses.newDirectInstance(IntValue.class); + LongValue heapValue = DataValueClasses.newInstance(LongValue.class); + LongValue directValue = DataValueClasses.newDirectInstance(LongValue.class); + + heapKey.setValue(1); + heapValue.setValue(1); + map.put(heapKey, heapValue); + assertEquals(1, map.get(heapKey).getValue()); + assertEquals(1, map.getUsing(heapKey, directValue).getValue()); + + ((Byteable) directValue).bytes(null, 0L); + directKey.setValue(1); + map.getUsing(directKey, directValue).addValue(1); + assertEquals(2, map.getUsing(directKey, heapValue).getValue()); + + directKey.setValue(2); + heapValue.setValue(3); + map.put(directKey, heapValue); + assertEquals(3, map.get(directKey).getValue()); + } +}