ignite-950: protocol optimizations
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/2e8bdec6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/2e8bdec6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/2e8bdec6 Branch: refs/heads/ignite-950 Commit: 2e8bdec625337ca33b3c58fbd70fae6f40104d2f Parents: f746e4b Author: Denis Magda <[email protected]> Authored: Mon Jun 29 11:00:03 2015 +0300 Committer: Denis Magda <[email protected]> Committed: Mon Jun 29 11:00:03 2015 +0300 ---------------------------------------------------------------------- .../cache/CacheIndexedObjectImpl.java | 13 +- .../IgniteCacheObjectProcessorImpl.java | 4 +- .../ignite/internal/util/io/GridDataInput.java | 9 ++ .../internal/util/io/GridUnsafeDataInput.java | 5 + .../optimized/OptimizedClassDescriptor.java | 15 +- .../OptimizedMarshalAwareMetaCollector.java | 2 +- .../optimized/OptimizedMarshallerExt.java | 10 +- .../optimized/OptimizedObjectInputStream.java | 101 ++++++------ .../optimized/OptimizedObjectMetadata.java | 159 +++++++------------ .../optimized/OptimizedObjectOutputStream.java | 73 ++++----- .../OptimizedObjectOutputStreamExt.java | 86 ++-------- .../OptimizedMarshallerExtSelfTest.java | 29 +++- 12 files changed, 211 insertions(+), 295 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java index c51d98c..8cf7085 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheIndexedObjectImpl.java @@ -27,6 +27,7 @@ import sun.misc.*; import java.io.*; import java.nio.*; +import java.util.concurrent.*; /** * Cache object implementation for classes that support footer injection is their serialized form thus enabling fields @@ -92,6 +93,9 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter { public CacheIndexedObjectImpl(Object val, byte[] valBytes, int start, int len) { assert val != null || (valBytes != null && start >= 0 && len > 0); + if (valBytes != null && val != null) + val = null; + this.val = val; this.valBytes = valBytes; this.start = start; @@ -200,8 +204,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter { Object val = ctx.processor().unmarshal(ctx, valBytes, start, len, ctx.kernalContext().config().getClassLoader()); - if (ctx.storeValue()) - this.val = val; + //if (ctx.storeValue()) + // this.val = val; return val; } @@ -326,7 +330,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter { * @return {@code true} if detached. */ protected boolean detached() { - return start == 0 && len == valBytes.length; + return true; + //return start == 0 && len == valBytes.length; } /** @@ -343,6 +348,8 @@ public class CacheIndexedObjectImpl extends CacheObjectAdapter { start = 0; len = valBytes.length; + + val = null; } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java index 5456fad..730b5d5 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java @@ -511,7 +511,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme try { toMarshaledFormIfNeeded(ctx); - if (ctx.storeValue()) { + /*if (ctx.storeValue()) { ClassLoader ldr = ctx.p2pEnabled() ? IgniteUtils.detectClass(this.val).getClassLoader() : val.getClass().getClassLoader(); @@ -519,7 +519,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme ctx.processor().unmarshal(ctx, valBytes, start, len, ldr); return new CacheIndexedObjectImpl(val, valBytes, start, len); - } + }*/ return new CacheIndexedObjectImpl(null, valBytes, start, len); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java index 975fb68..4d06d81 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridDataInput.java @@ -194,4 +194,13 @@ public interface GridDataInput extends DataInput { * @return Integer value. */ public int readInt(int pos); + + /** + * Fast read of long value at {@code pos}. + * + * @param pos Position in array. + * + * @return Long value. + */ + public long readLong(int pos); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java index ed04cfe..5c15c4c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/io/GridUnsafeDataInput.java @@ -511,6 +511,11 @@ public class GridUnsafeDataInput extends InputStream implements GridDataInput { return UNSAFE.getInt(buf, byteArrOff + pos); } + /** {@inheritDoc} */ + @Override public long readLong(int pos) { + return UNSAFE.getLong(buf, byteArrOff + pos); + } + /** * Reads in the "body" (i.e., the UTF representation minus the 2-byte * or 8-byte length header) of a UTF encoding, which occupies the next http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java index 9773d40..3596548 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java @@ -436,7 +436,6 @@ public class OptimizedClassDescriptor { fieldInfo = new FieldInfo(null, serField.getName(), -1, - resolveFieldId(serField.getName()), fieldType(serField.getType())); } else { @@ -445,7 +444,6 @@ public class OptimizedClassDescriptor { fieldInfo = new FieldInfo(f, serField.getName(), UNSAFE.objectFieldOffset(f), - resolveFieldId(serField.getName()), fieldType(serField.getType())); } @@ -471,7 +469,6 @@ public class OptimizedClassDescriptor { FieldInfo fieldInfo = new FieldInfo(f, f.getName(), UNSAFE.objectFieldOffset(f), - resolveFieldId(f.getName()), fieldType(f.getType())); clsFields.add(fieldInfo); @@ -891,8 +888,6 @@ public class OptimizedClassDescriptor { /** Field name. */ private final String fieldName; - /** ID calculated from field's name. */ - private final int fieldId; /** * @param field Field. @@ -900,19 +895,11 @@ public class OptimizedClassDescriptor { * @param offset Field offset. * @param type Grid optimized field type. */ - FieldInfo(Field field, String name, long offset, int fieldId, OptimizedFieldType type) { + FieldInfo(Field field, String name, long offset, OptimizedFieldType type) { this.field = field; fieldOffs = offset; fieldType = type; fieldName = name; - this.fieldId = fieldId; - } - - /** - * @return Field ID. - */ - public int id() { - return fieldId; } /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshalAwareMetaCollector.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshalAwareMetaCollector.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshalAwareMetaCollector.java index c4fb9d4..79c5f24 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshalAwareMetaCollector.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshalAwareMetaCollector.java @@ -174,6 +174,6 @@ class OptimizedMarshalAwareMetaCollector implements OptimizedFieldsWriter { * @param type Field type. */ private void putFieldToMeta(String fieldName, OptimizedFieldType type) { - meta.addMeta(OptimizedMarshallerUtils.resolveFieldId(fieldName), type); + meta.addField(fieldName, type); } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java index fd0fa47..91e5a9a 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExt.java @@ -40,16 +40,16 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { static final byte FOOTER_LEN_OFF = 2; /** */ - static final int FOOTER_BODY_LEN_MASK = 0x3FFFFFFF; + static final byte FOOTER_HANDLES_FLAG_OFF = 3; /** */ - static final int FOOTER_BODY_IS_HANDLE_MASK = 0x40000000; + static final int FOOTER_BODY_OFF_MASK = 0x3FFFFFFF; /** */ - static final byte FOOTER_BODY_HANDLE_MASK_BIT = 30; + static final int FOOTER_BODY_IS_HANDLE_MASK = 0x40000000; /** */ - public static final byte VARIABLE_LEN = -1; + static final byte FOOTER_BODY_HANDLE_MASK_BIT = 30; /** */ private final static ConcurrentHashMap<Class<?>, Boolean> indexingEnabledCache = new ConcurrentHashMap<>(); @@ -173,7 +173,7 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { for (ClassFields clsFields : desc.fields().fieldsList()) for (FieldInfo info : clsFields.fieldInfoList()) - meta.addMeta(info.id(), info.type()); + meta.addField(info.name(), info.type()); metaHandler.addMeta(desc.typeId(), meta); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java index 6e7d7d6..5a35586 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java @@ -500,15 +500,15 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt * @throws ClassNotFoundException In case of error. * @throws IOException In case of error. */ - HashMap<Integer, Object> readFields( OptimizedObjectMetadata meta) throws ClassNotFoundException, + HashMap<Integer, Object> readFields(OptimizedObjectMetadata meta) throws ClassNotFoundException, IOException { HashMap<Integer, Object> fieldsValues = new HashMap<>(); - for (OptimizedObjectMetadata.FieldInfo fieldInfo : meta.getMeta()) { + for (Map.Entry<Integer, OptimizedObjectMetadata.FieldInfo> entry : meta.metaList()) { Object val; - switch ((fieldInfo.type())) { + switch ((entry.getValue().type())) { case BYTE: readFieldType(); @@ -572,10 +572,10 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt break; default: - throw new IgniteException("Unknown field type: " + fieldInfo.type()); + throw new IgniteException("Unknown field type: " + entry.getValue().type()); } - fieldsValues.put(fieldInfo.id(), val); + fieldsValues.put(entry.getKey(), val); } return fieldsValues; @@ -1315,7 +1315,15 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt if (type != SERIALIZABLE && type != MARSHAL_AWARE) return false; - FieldRange range = fieldRange(fieldName, start); + FieldRange range; + + try { + range = fieldRange(fieldName, start); + } + catch (IgniteFieldNotFoundException e) { + // Ignore + return false; + } return range != null && range.start >= 0; } @@ -1368,17 +1376,14 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt * @param start Object's start offset. * @return positive range or {@code null} if the object doesn't have such a field. * @throws IOException in case of error. + * @throws IgniteFieldNotFoundException In case if there is no such a field. */ - private FieldRange fieldRange(String fieldName, int start) throws IOException { + private FieldRange fieldRange(String fieldName, int start) throws IOException, IgniteFieldNotFoundException { int pos = start + 1; - int fieldId = resolveFieldId(fieldName); - int typeId = in.readInt(pos); pos += 4; - int clsNameLen = 0; - if (typeId == 0) { int oldPos = in.position(); @@ -1386,8 +1391,6 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt typeId = OptimizedMarshallerUtils.resolveTypeId(readUTF(), mapper); - clsNameLen = in.position() - pos; - in.position(oldPos); } @@ -1402,58 +1405,58 @@ public class OptimizedObjectInputStream extends ObjectInputStream implements Opt short footerLen = in.readShort(end - FOOTER_LEN_OFF); if (footerLen == EMPTY_FOOTER) - return null; + throw new IgniteFieldNotFoundException("Object doesn't have a field named: " + fieldName); + + if (range == null) + range = new FieldRange(); - // Calculating footer offset. +2 - skipping length at the beginning + // Calculating start footer offset. +2 - skipping length at the beginning pos = (end - footerLen) + 2; - int fieldOff = 0; + int fieldIdx = meta.fieldIndex(fieldName); + int fieldsCnt = meta.size(); - for (OptimizedObjectMetadata.FieldInfo info : meta.getMeta()) { - int len; - boolean isHandle; + if (fieldIdx >= fieldsCnt) + throw new IOException("Wrong field index for field name [idx=" + fieldIdx + ", name=" + fieldName + "]"); - if (info.length() == VARIABLE_LEN) { - int fieldInfo = in.readInt(pos); + boolean hasHandles = in.readByte(end - FOOTER_HANDLES_FLAG_OFF) == 1; - pos += 4; - len = fieldInfo & FOOTER_BODY_LEN_MASK; - isHandle = ((fieldInfo & FOOTER_BODY_IS_HANDLE_MASK) >> FOOTER_BODY_HANDLE_MASK_BIT) == 1; - } - else { - len = info.length(); - isHandle = false; - } + if (hasHandles) { + long fieldInfo = in.readLong(pos + fieldIdx * 8); - if (info.id() == fieldId) { - if (range == null) - range = new FieldRange(); + boolean isHandle = ((fieldInfo & FOOTER_BODY_IS_HANDLE_MASK) >> FOOTER_BODY_HANDLE_MASK_BIT) == 1; - if (!isHandle) { - //object header len: 1 - for type, 4 - for type ID, 2 - for checksum. - fieldOff += 1 + 4 + clsNameLen + 2; + range.start = (int)(fieldInfo & FOOTER_BODY_OFF_MASK); - range.start = start + fieldOff; - range.len = len; - } - else { - range.start = in.readInt(pos); - range.len = in.readInt(pos + 4); - } + if (isHandle) { + range.len = (int)(fieldInfo >>> 32); + + if (range.len == 0) + // Field refers to its object. + range.len = (end - start) - footerLen; return range; } - else { - fieldOff += len; + } + else + range.start = in.readInt(pos + fieldIdx * 4) & FOOTER_BODY_OFF_MASK; - if (isHandle) { - pos += 8; - fieldOff += 8; - } + if (fieldIdx == 0) { + if (fieldsCnt > 1) { + int nextFieldOff = in.readInt(pos + (fieldIdx + 1) * 4); + range.len = nextFieldOff - range.start; } + else + range.len = (end - footerLen) - range.start; + } + else if (fieldIdx == fieldsCnt - 1) + range.len = (end - footerLen) - range.start; + else { + int nextFieldOff = in.readInt(pos + (fieldIdx + 1) * 4); + range.len = nextFieldOff - range.start; } - return null; + return range; } /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectMetadata.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectMetadata.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectMetadata.java index 97facca..9e5a18a 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectMetadata.java @@ -17,21 +17,21 @@ package org.apache.ignite.marshaller.optimized; -import org.apache.ignite.*; - import java.io.*; import java.util.*; /** - * Metadata that keeps fields information. Used in conjunction with the footer that is added to some objects during - * marshalling. + * Metadata that keeps fields' name to id mapping. */ public class OptimizedObjectMetadata implements Externalizable { /** */ private static final long serialVersionUID = 0L; /** */ - private List<FieldInfo> fieldsInfo; + private LinkedHashMap<Integer, FieldInfo> indexes; + + /** */ + private short counter; /** Constructor. */ public OptimizedObjectMetadata() { @@ -39,143 +39,92 @@ public class OptimizedObjectMetadata implements Externalizable { } /** - * Adds meta for a new field. + * Adds field to metadata list assigning an index to it that is used to locate field bucket in the footer of + * object's serialized form. + * + * @param fieldName Field name. + */ + public void addField(String fieldName, OptimizedFieldType type) { + if (indexes == null) + indexes = new LinkedHashMap<>(); + + indexes.put(OptimizedMarshallerUtils.resolveFieldId(fieldName), new FieldInfo(type, counter++)); + } + + /** + * Returns an index assigned to the field. The index is used to locate field bucket in the footer of + * object's serialized form. * - * @param fieldId Field ID. - * @param fieldType Field type. + * @param fieldName Field name. + * @return Index. + * @throws IgniteFieldNotFoundException If object doesn't have such a field. */ - public void addMeta(int fieldId, OptimizedFieldType fieldType) { - if (fieldsInfo == null) - fieldsInfo = new ArrayList<>(); + public int fieldIndex(String fieldName) throws IgniteFieldNotFoundException { + if (indexes == null) + throw new IgniteFieldNotFoundException("Object doesn't have field named: " + fieldName); + FieldInfo info = indexes.get(OptimizedMarshallerUtils.resolveFieldId(fieldName)); + if (info == null) + throw new IgniteFieldNotFoundException("Object doesn't have field named: " + fieldName); - fieldsInfo.add(new FieldInfo(fieldId, fieldType)); + return info.index(); } /** - * Gets {@link OptimizedObjectMetadata.FieldInfo} at the {@code index}. + * Returns meta list. * - * @param index Position. - * @return Field meta info. + * @return Meta list. */ - public FieldInfo getMeta(int index) { - return fieldsInfo.get(index); + public Set<Map.Entry<Integer, FieldInfo>> metaList() { + return indexes.entrySet(); } + /** - * Returns all the metadata stored for the object. + * Returns number of fields. * - * @return Metadata collection. + * @return Number of fields. */ - public List<FieldInfo> getMeta() { - return Collections.unmodifiableList(fieldsInfo); + public int size() { + return indexes.size(); } /** {@inheritDoc} */ @Override public void writeExternal(ObjectOutput out) throws IOException { - if (fieldsInfo == null) { - out.writeInt(0); - return; - } - - out.writeInt(fieldsInfo.size()); - - for (FieldInfo fieldInfo : fieldsInfo) { - out.writeInt(fieldInfo.id); - out.writeByte(fieldInfo.type.ordinal()); - } + out.writeObject(indexes); } /** {@inheritDoc} */ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - int size = in.readInt(); - - fieldsInfo = new ArrayList<>(size); - - for (int i = 0; i < size; i++) - fieldsInfo.add(new FieldInfo(in.readInt(), OptimizedFieldType.values()[in.readByte()])); + indexes = (LinkedHashMap<Integer, FieldInfo>)in.readObject(); } /** * Field info. */ - public static class FieldInfo { - /** Field ID. */ - private int id; - - /** Field len. */ - private int len; - - /** Field type. */ + public static class FieldInfo implements Serializable { + /** */ private OptimizedFieldType type; + /** */ + private short index; + /** * Constructor. - * - * @param id Field ID. - * @param type Field len. + * @param type + * @param index */ - public FieldInfo(int id, OptimizedFieldType type) { - this.id = id; + public FieldInfo(OptimizedFieldType type, short index) { this.type = type; - - len = 1; - - switch (type) { - case BYTE: - case BOOLEAN: - len += 1; - break; - - case SHORT: - case CHAR: - len += 2; - break; - - case INT: - case FLOAT: - len += 4; - break; - - case LONG: - case DOUBLE: - len += 8; - break; - - case OTHER: - len = OptimizedMarshallerExt.VARIABLE_LEN; - break; - - default: - throw new IgniteException("Unknown field type: " + type); - } - - assert len != 1; + this.index = index; } - /** - * Returns ID. - * @return ID. - */ - public int id() { - return id; - } - - /** - * Returns length. - * @return Lenght. - */ - public int length() { - return len; - } - - /** - * Returns field type. - * - * @return Field type. - */ public OptimizedFieldType type() { return type; } + + public short index() { + return index; + } } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java index 2bb71e9..c697c2e 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java @@ -538,12 +538,12 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O @SuppressWarnings("ForLoopReplaceableByForEach") private void writeFields(Object obj, OptimizedClassDescriptor.ClassFields fields, Footer footer) throws IOException { - int size; + int off; for (int i = 0; i < fields.size(); i++) { OptimizedClassDescriptor.FieldInfo t = fields.get(i); - size = out.size(); + off = out.offset(); switch (t.type()) { case BYTE: @@ -631,17 +631,14 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O GridHandleTable.ObjectInfo objInfo = writeObject0(getObject(obj, t.offset())); if (footer != null && objInfo != null) { - footer.putHandle(t.id(), objInfo); + footer.addNextHandleField(objInfo.position(), objInfo.length()); continue; } } } - if (footer != null && t.field() != null) { - int fieldLen = out.size() - size; - - footer.put(t.id(), t.type(), fieldLen); - } + if (footer != null && t.field() != null) + footer.addNextFieldOff(off); } } @@ -832,13 +829,13 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O if (curPut == null) throw new NotActiveException("putFields() was not called."); - int size; + int off; Footer footer = curPut.curFooter; for (IgniteBiTuple<OptimizedClassDescriptor.FieldInfo, Object> t : curPut.objs) { - size = out.size(); + off = out.offset(); switch (t.get1().type()) { case BYTE: @@ -909,16 +906,13 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O GridHandleTable.ObjectInfo objInfo = writeObject0(t.get2()); if (footer != null && objInfo != null) { - footer.putHandle(t.get1().id(), objInfo); + footer.addNextHandleField(objInfo.position(), objInfo.length()); continue; } } - if (footer != null) { - int fieldLen = out.size() - size; - - footer.put(t.get1().id(), t.get1().type(), fieldLen); - } + if (footer != null) + footer.addNextFieldOff(off); } } @@ -955,58 +949,58 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O /** {@inheritDoc} */ @Override public void writeByte(String fieldName, byte val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(BYTE); out.writeByte(val); - putFieldToFooter(fieldName, OptimizedFieldType.BYTE, 1); } /** {@inheritDoc} */ @Override public void writeShort(String fieldName, short val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(SHORT); out.writeShort(val); - putFieldToFooter(fieldName, OptimizedFieldType.SHORT, 2); } /** {@inheritDoc} */ @Override public void writeInt(String fieldName, int val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(INT); out.writeInt(val); - putFieldToFooter(fieldName, OptimizedFieldType.INT, 4); } /** {@inheritDoc} */ @Override public void writeLong(String fieldName, long val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(LONG); out.writeLong(val); - putFieldToFooter(fieldName, OptimizedFieldType.LONG, 8); } /** {@inheritDoc} */ @Override public void writeFloat(String fieldName, float val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(FLOAT); out.writeFloat(val); - putFieldToFooter(fieldName, OptimizedFieldType.FLOAT, 4); } /** {@inheritDoc} */ @Override public void writeDouble(String fieldName, double val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(DOUBLE); out.writeDouble(val); - putFieldToFooter(fieldName, OptimizedFieldType.DOUBLE, 8); } /** {@inheritDoc} */ @Override public void writeChar(String fieldName, char val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(CHAR); out.writeChar(val); - putFieldToFooter(fieldName, OptimizedFieldType.CHAR, 2); } /** {@inheritDoc} */ @Override public void writeBoolean(String fieldName, boolean val) throws IOException { + putFieldOffsetToFooter(out.offset()); writeFieldType(BOOLEAN); out.writeBoolean(val); - putFieldToFooter(fieldName, OptimizedFieldType.BOOLEAN, 1); } /** {@inheritDoc} */ @@ -1016,10 +1010,8 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O /** {@inheritDoc} */ @Override public void writeObject(String fieldName, @Nullable Object obj) throws IOException { - int pos = out.offset(); - + putFieldOffsetToFooter(out.offset()); writeObject(obj); - putFieldToFooter(fieldName, OptimizedFieldType.OTHER, out.offset() - pos); } /** {@inheritDoc} */ @@ -1093,14 +1085,12 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O } /** - * Puts field to the footer. + * Puts field's offset to the footer. * - * @param fieldName Field name. - * @param type Field type. - * @param len Field length. + * @param off Field offset. */ - private void putFieldToFooter(String fieldName, OptimizedFieldType type, int len) { - marshalAwareFooters.peek().put(OptimizedMarshallerUtils.resolveFieldId(fieldName), type, len); + private void putFieldOffsetToFooter(int off) { + marshalAwareFooters.peek().addNextFieldOff(off); } /** @@ -1230,22 +1220,19 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream implements O void indexingSupported(boolean indexingSupported); /** - * Puts type ID and its value len to the footer. + * Adds offset of a field that must be placed next to the footer. * - * @param fieldId Field ID. - * @param fieldType Field type. - * @param len Total number of bytes occupied by type's value. + * @param off Field offset. */ - void put(int fieldId, OptimizedFieldType fieldType, int len); - + void addNextFieldOff(int off); /** - * Puts handle ID for the given field ID. + * Adds handle's offset of a field that must be placed next to the footer. * - * @param fieldId Field ID. - * @param objInfo Object's, referred by handle, info. + * @param handleOff Handle offset. + * @param handleLen Handle length. */ - void putHandle(int fieldId, GridHandleTable.ObjectInfo objInfo); + void addNextHandleField(int handleOff, int handleLen); /** * Writes footer content to the OutputStream. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStreamExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStreamExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStreamExt.java index 9833e98..ad5b515 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStreamExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStreamExt.java @@ -58,10 +58,7 @@ public class OptimizedObjectOutputStreamExt extends OptimizedObjectOutputStream */ private class FooterImpl implements OptimizedObjectOutputStream.Footer { /** */ - private ArrayList<Meta> data; - - /** */ - private HashMap<Integer, GridHandleTable.ObjectInfo> handles; + private ArrayList<Long> data; /** */ private boolean hasHandles; @@ -75,28 +72,15 @@ public class OptimizedObjectOutputStreamExt extends OptimizedObjectOutputStream } /** {@inheritDoc} */ - @Override public void put(int fieldId, OptimizedFieldType fieldType, int len) { - if (data == null) - return; - - if (fieldType == OptimizedFieldType.OTHER) - data.add(new Meta(fieldId, len)); + @Override public void addNextFieldOff(int off) { + data.add((long)(off & ~FOOTER_BODY_IS_HANDLE_MASK)); } /** {@inheritDoc} */ - @Override public void putHandle(int fieldId, GridHandleTable.ObjectInfo objInfo) { - if (data == null) - return; + @Override public void addNextHandleField(int handleOff, int handleLength) { + hasHandles = true; - if (!hasHandles) { - hasHandles = true; - handles = new HashMap<>(); - } - - handles.put(fieldId, objInfo); - - // length of handle fields is 5 bytes. - put(fieldId, OptimizedFieldType.OTHER, 5); + data.add(((long)handleLength << 32) | (handleOff | FOOTER_BODY_IS_HANDLE_MASK)); } /** {@inheritDoc} */ @@ -104,61 +88,25 @@ public class OptimizedObjectOutputStreamExt extends OptimizedObjectOutputStream if (data == null) writeShort(EMPTY_FOOTER); else { - int bodyEnd = out.offset(); - - // +4 - 2 bytes for footer len at the beginning, 2 bytes for footer len at the end. - short footerLen = (short)(data.size() * 4 + 4); - - if (hasHandles) - footerLen += handles.size() * 8; + // +5 - 2 bytes for footer len at the beginning, 2 bytes for footer len at the end, 1 byte for handles + // indicator flag. + short footerLen = (short)(data.size() * (hasHandles ? 8 : 4) + 5); writeShort(footerLen); if (hasHandles) { - for (Meta fieldMeta : data) { - GridHandleTable.ObjectInfo objInfo = handles.get(fieldMeta.fieldId); - - if (objInfo == null) - writeInt(fieldMeta.fieldLen & ~FOOTER_BODY_IS_HANDLE_MASK); - else { - writeInt(fieldMeta.fieldLen | FOOTER_BODY_IS_HANDLE_MASK); - writeInt(objInfo.position()); - - if (objInfo.length() == 0) - // field refers to its own object that hasn't set total length yet. - writeInt((bodyEnd - objInfo.position()) + footerLen); - else - writeInt(objInfo.length()); - } - } + for (long body : data) + writeLong(body); + } + else { + for (long body : data) + writeInt((int)body); } - else - for (Meta fieldMeta : data) - // writing field len and resetting is handle mask - writeInt(fieldMeta.fieldLen & ~FOOTER_BODY_IS_HANDLE_MASK); + + writeByte(hasHandles ? 1 : 0); writeShort(footerLen); } } } - - /** - * - */ - private static class Meta { - /** */ - int fieldId; - - /** */ - int fieldLen; - - /** - * @param fieldId - * @param fieldLen - */ - public Meta(int fieldId, int fieldLen) { - this.fieldId = fieldId; - this.fieldLen = fieldLen; - } - } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2e8bdec6/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java index 0e9fb61..94a7523 100644 --- a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerExtSelfTest.java @@ -22,6 +22,7 @@ import org.apache.ignite.marshaller.*; import org.apache.ignite.testframework.junits.common.*; import java.io.*; +import java.lang.reflect.*; import java.util.*; import java.util.concurrent.*; @@ -106,11 +107,19 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest // Must be returned in a wrapped form, since metadata was added enabling the footer. CacheIndexedObjectImpl cacheObject = marsh.readField("o2", arr, 0, arr.length, null); + arr = cacheObject.valueBytes(null); + Field start = cacheObject.getClass().getDeclaredField("start"); + start.setAccessible(true); + + Field len = cacheObject.getClass().getDeclaredField("len"); + len.setAccessible(true); + // Check enclosed objects fields - assertTrue(marsh.hasField("i", arr, 0, arr.length)); - assertEquals(testObj.o2.i, (int)marsh.readField("i", arr, 0, arr.length, null)); + assertTrue(marsh.hasField("i", arr, start.getInt(cacheObject), len.getInt(cacheObject))); + assertEquals(testObj.o2.i, (int)marsh.readField("i", arr, start.getInt(cacheObject), len.getInt(cacheObject), + null)); } /** @@ -174,14 +183,26 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest CacheIndexedObjectImpl cacheObj = marsh.readField("aware", arr, 0, arr.length, null); byte[] cacheObjArr = cacheObj.valueBytes(null); - Date date = marsh.readField("date", cacheObjArr, 0, cacheObjArr.length, null); + Field start = cacheObj.getClass().getDeclaredField("start"); + start.setAccessible(true); + + Field len = cacheObj.getClass().getDeclaredField("len"); + len.setAccessible(true); + + Date date = marsh.readField("date", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null); assertEquals(test.aware.date, date); cacheObj = marsh.readField("testObject2", arr, 0, arr.length, null); cacheObjArr = cacheObj.valueBytes(null); - int n = marsh.readField("i", cacheObjArr, 0, cacheObjArr.length, null); + start = cacheObj.getClass().getDeclaredField("start"); + start.setAccessible(true); + + len = cacheObj.getClass().getDeclaredField("len"); + len.setAccessible(true); + + int n = marsh.readField("i", cacheObjArr, start.getInt(cacheObj), len.getInt(cacheObj), null); assertEquals(test.testObject2.i, n);
