ignite-950: adding handles to footer
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/5e7fcc1f Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/5e7fcc1f Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/5e7fcc1f Branch: refs/heads/ignite-950 Commit: 5e7fcc1f1759bbb2f87dd64cc3d6487cd5722e40 Parents: 25d0da2 Author: Denis Magda <dma...@gridgain.com> Authored: Thu Jun 18 16:25:22 2015 +0300 Committer: Denis Magda <dma...@gridgain.com> Committed: Thu Jun 18 16:25:22 2015 +0300 ---------------------------------------------------------------------- .../ignite/internal/util/GridHandleTable.java | 32 ++++++++-- .../optimized/OptimizedClassDescriptor.java | 4 +- .../optimized/OptimizedObjectOutputStream.java | 24 +++---- .../optimized/ext/OptimizedMarshallerExt.java | 3 + .../ext/OptimizedObjectInputStreamExt.java | 36 +++++++++-- .../ext/OptimizedObjectOutputStreamExt.java | 66 ++++++++++++++------ 6 files changed, 118 insertions(+), 47 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/modules/core/src/main/java/org/apache/ignite/internal/util/GridHandleTable.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridHandleTable.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridHandleTable.java index 05a089c..6b63360 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/util/GridHandleTable.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridHandleTable.java @@ -47,6 +47,9 @@ public class GridHandleTable { /** Maps handle value -> next candidate handle value. */ private int[] next; + /** Handle absolute position in the output stream. */ + private int[] positions; + /** Maps handle value -> associated object. */ private Object[] objs; @@ -68,6 +71,7 @@ public class GridHandleTable { spine = new int[initCap]; next = new int[initCap]; objs = new Object[initCap]; + positions = new int[initCap]; spineEmpty = new int[initCap]; nextEmpty = new int[initCap]; @@ -84,9 +88,10 @@ public class GridHandleTable { * no mapping found. * * @param obj Object. + * @param pos Current absolute position in output stream. * @return Handle. */ - public int lookup(Object obj) { + public int lookup(Object obj, int pos) { int idx = hash(obj) % spine.length; if (size > 0) { @@ -101,7 +106,7 @@ public class GridHandleTable { if (size >= threshold) growSpine(); - insert(obj, size, idx); + insert(obj, size, idx, pos); size++; @@ -109,6 +114,16 @@ public class GridHandleTable { } /** + * Returns handle absolute position in output stream. + * + * @param handle Handle. + * @return Absolute position. + */ + public int position(int handle) { + return positions[handle]; + } + + /** * Resets table to its initial (empty) state. */ public void clear() { @@ -116,6 +131,7 @@ public class GridHandleTable { UNSAFE.copyMemory(nextEmpty, intArrOff, next, intArrOff, nextEmpty.length << 2); Arrays.fill(objs, null); + Arrays.fill(positions, 0); size = 0; } @@ -134,10 +150,12 @@ public class GridHandleTable { * @param obj Object. * @param handle Handle. * @param idx Index. + * @param pos Position in output stream. */ - private void insert(Object obj, int handle, int idx) { + private void insert(Object obj, int handle, int idx, int pos) { objs[handle] = obj; next[handle] = spine[idx]; + positions[handle] = pos; spine[idx] = handle; } @@ -161,7 +179,7 @@ public class GridHandleTable { int idx = hash(obj) % spine.length; - insert(objs[i], i, idx); + insert(objs[i], i, idx, positions[i]); } } @@ -184,6 +202,12 @@ public class GridHandleTable { System.arraycopy(objs, 0, newObjs, 0, size); objs = newObjs; + + int[] newPositions = new int[newLen]; + + UNSAFE.copyMemory(positions, intArrOff, newPositions, intArrOff, size << 2); + + positions = newPositions; } /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/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 ae3ae77..d77551f 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 @@ -724,12 +724,10 @@ public class OptimizedClassDescriptor { "set OptimizedMarshaller.setRequireSerializable() to false " + "(note that performance may degrade if object is not Serializable): " + name); - int headerPos = out.out().size() - 1; - writeTypeData(out); out.writeShort(checksum); - out.writeSerializable(obj, writeObjMtds, fields, headerPos); + out.writeSerializable(obj, writeObjMtds, fields); break; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/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 a88da95..90e2a85 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 @@ -154,7 +154,7 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { * @param obj Object. * @throws IOException In case of error. * - * @return Handle ID that has already written {@code obj} or -1 if the {@code obj} has not been written before. + * @return Handle's position in {@link #out} or -1 if the {@code obj} has not been written before. */ private int writeObject0(Object obj) throws IOException { curObj = null; @@ -204,7 +204,7 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { } if (!desc.isPrimitive() && !desc.isEnum() && !desc.isClass()) - handle = handles.lookup(obj); + handle = handles.lookup(obj, out.offset()); if (obj0 != obj) { obj = obj0; @@ -218,6 +218,8 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { if (handle >= 0) { writeByte(HANDLE); writeInt(handle); + + handle = handles.position(handle); } else desc.write(this, obj); @@ -303,18 +305,15 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { * @param obj Object. * @param mtds {@code writeObject} methods. * @param fields class fields details. - * @param headerPos Object's header position in the OutputStream. * @throws IOException In case of error. */ @SuppressWarnings("ForLoopReplaceableByForEach") - void writeSerializable(Object obj, List<Method> mtds, OptimizedClassDescriptor.Fields fields, int headerPos) + void writeSerializable(Object obj, List<Method> mtds, OptimizedClassDescriptor.Fields fields) throws IOException { Footer footer = createFooter(obj.getClass()); - if (footer != null) { + if (footer != null) footer.fields(fields); - footer.headerPos(headerPos); - } for (int i = 0; i < mtds.size(); i++) { Method mtd = mtds.get(i); @@ -978,13 +977,6 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { void fields(OptimizedClassDescriptor.Fields fields); /** - * Sets field's header absolute position. - * - * @param pos Absolute position. - */ - void headerPos(int pos); - - /** * Puts type ID and its value len to the footer. * * @param fieldId Field ID. @@ -998,9 +990,9 @@ public class OptimizedObjectOutputStream extends ObjectOutputStream { * Puts handle ID for the given field ID. * * @param fieldId Field ID. - * @param handleId Handle ID. + * @param handlePos Handle position in output stream. */ - void putHandle(int fieldId, int handleId); + void putHandle(int fieldId, int handlePos); /** * Writes footer content to the OutputStream. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java index 1a451e1..a41a331 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java @@ -41,6 +41,9 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { static final byte VARIABLE_LEN = -1; /** */ + static final byte NOT_A_HANDLE = -1; + + /** */ private OptimizedMarshallerExtMetaHandler metaHandler; /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java index 7ab56a2..7c8cc3c 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java @@ -16,6 +16,7 @@ */ package org.apache.ignite.marshaller.optimized.ext; +import org.apache.ignite.*; import org.apache.ignite.internal.processors.cache.*; import org.apache.ignite.internal.util.io.*; import org.apache.ignite.marshaller.*; @@ -167,6 +168,11 @@ public class OptimizedObjectInputStreamExt extends OptimizedObjectInputStream { if (footerLen == EMPTY_FOOTER) return null; + // reading 'hasHandles' flag. 1 byte - additional offset to get to the flag position. + in.position(in.position() - FOOTER_LEN_OFF - 1); + + boolean hasHandles = in.readBoolean(); + // 4 - skipping length at the beginning int footerOff = (end - footerLen) + 4; in.position(footerOff); @@ -175,13 +181,33 @@ public class OptimizedObjectInputStreamExt extends OptimizedObjectInputStream { for (OptimizedObjectMetadata.FieldInfo info : meta.getMeta()) { if (info.id == fieldId) { - //object header len: 1 - for type, 4 - for type ID, 2 - for checksum. - fieldOff += 1 + 4 + clsNameLen + 2; + int len = info.len == VARIABLE_LEN ? in.readInt() : info.len; + int handlePos; + + if (hasHandles && info.len == VARIABLE_LEN) + handlePos = in.readInt(); + else + handlePos = NOT_A_HANDLE; + + if (handlePos == NOT_A_HANDLE) { + //object header len: 1 - for type, 4 - for type ID, 2 - for checksum. + fieldOff += 1 + 4 + clsNameLen + 2; + + return new FieldRange(start + fieldOff, len); + } + else { + throw new IgniteException("UNSUPPORTED YET"); + } + } + else { + fieldOff += info.len == VARIABLE_LEN ? in.readInt() : info.len; + + if (hasHandles) { + in.skipBytes(4); + fieldOff += 4; + } - return new FieldRange(start + fieldOff, info.len == VARIABLE_LEN ? in.readShort() : info.len); } - else - fieldOff += info.len == VARIABLE_LEN ? in.readShort() : info.len; } return null; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/5e7fcc1f/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectOutputStreamExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectOutputStreamExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectOutputStreamExt.java index 823caf5..4ef0d4a 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectOutputStreamExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectOutputStreamExt.java @@ -72,37 +72,52 @@ public class OptimizedObjectOutputStreamExt extends OptimizedObjectOutputStream */ private class FooterImpl implements OptimizedObjectOutputStream.Footer { /** */ - private ArrayList<Short> data; + private ArrayList<Integer> data; /** */ - private int headerPos; + private ArrayList<Integer> fields; + + /** */ + private HashMap<Integer, Integer> handles; + + /** */ + private boolean hasHandles; /** {@inheritDoc} */ @Override public void fields(OptimizedClassDescriptor.Fields fields) { - if (fields.fieldsIndexingSupported()) + if (fields.fieldsIndexingSupported()) { data = new ArrayList<>(); + this.fields = new ArrayList<>(); + } else data = null; } /** {@inheritDoc} */ - public void headerPos(int pos) { - headerPos = pos; - } - - /** {@inheritDoc} */ public void put(int fieldId, OptimizedFieldType fieldType, int len) { if (data == null) return; - // Considering that field's length will be no longer 2^15 (32 MB) - if (fieldType == OptimizedFieldType.OTHER) - data.add((short)len); + if (fieldType == OptimizedFieldType.OTHER) { + data.add(len); + fields.add(fieldId); + } } /** {@inheritDoc} */ - @Override public void putHandle(int fieldId, int handleId) { - disable(); + @Override public void putHandle(int fieldId, int handlePos) { + if (data == null) + return; + + if (!hasHandles) { + hasHandles = true; + handles = new HashMap<>(); + } + + handles.put(fieldId, handlePos); + + // length of handle fields is 5 bytes. + put(fieldId, OptimizedFieldType.OTHER, 5); } /** {@inheritDoc} */ @@ -110,16 +125,29 @@ public class OptimizedObjectOutputStreamExt extends OptimizedObjectOutputStream if (data == null) writeInt(EMPTY_FOOTER); else { - //12 - 4 bytes for len at the beginning, 4 bytes for len at the end, 4 bytes for object len. - int footerLen = data.size() * 2 + 12; + //9 - 4 bytes for len at the beginning, 4 bytes for len at the end, 1 byte for 'hasHandles' flag + int footerLen = data.size() * 4 + 9; + + if (hasHandles) + footerLen += data.size() * 4; writeInt(footerLen); - for (short fieldLen : data) - writeShort(fieldLen); + if (hasHandles) { + for (int i = 0; i < data.size(); i++) { + writeInt(data.get(i)); + + Integer handlePos = handles.get(fields.get(i)); + + writeInt(handlePos == null ? NOT_A_HANDLE : handlePos); + } + } + else { + for (int fieldLen : data) + writeInt(fieldLen); + } - // object total len - writeInt((out.size() - headerPos) + 8); + writeBoolean(hasHandles); writeInt(footerLen); }