You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2015/11/19 10:48:08 UTC
[07/10] ignite git commit: IGNITE-1816: Implemented compact footers.
IGNITE-1816: Implemented compact footers.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0b4a8f83
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0b4a8f83
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0b4a8f83
Branch: refs/heads/ignite-1753-1282
Commit: 0b4a8f831fe2d183e6e831c90da0d3fc86ac2ed0
Parents: 66c84ea
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Nov 18 14:54:38 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Nov 18 14:54:38 2015 +0300
----------------------------------------------------------------------
.../apache/ignite/internal/IgniteKernal.java | 6 +
.../ignite/internal/IgniteNodeAttributes.java | 3 +
.../portable/BinaryCachingMetadataHandler.java | 70 +
.../internal/portable/BinaryMetadata.java | 16 +-
.../portable/BinaryMetadataCollector.java | 49 +-
.../internal/portable/BinaryObjectEx.java | 2 +-
.../internal/portable/BinaryObjectImpl.java | 14 +-
.../portable/BinaryObjectOffheapImpl.java | 14 +-
.../internal/portable/BinaryReaderExImpl.java | 132 +-
.../internal/portable/BinaryTypeImpl.java | 7 +-
.../internal/portable/BinaryWriterExImpl.java | 161 +-
.../portable/PortableClassDescriptor.java | 102 +-
.../internal/portable/PortableContext.java | 66 +-
.../internal/portable/PortableSchema.java | 296 +-
.../ignite/internal/portable/PortableUtils.java | 457 ++-
.../builder/BinaryObjectBuilderImpl.java | 130 +-
.../portable/builder/PortableBuilderReader.java | 21 +-
.../portable/CacheObjectBinaryProcessor.java | 2 +-
.../CacheObjectBinaryProcessorImpl.java | 162 +-
.../platform/PlatformContextImpl.java | 10 +-
.../cpp/PlatformCppConfigurationClosure.java | 9 +-
.../PlatformDotNetConfigurationClosure.java | 9 +-
.../ignite/internal/util/IgniteUtils.java | 25 +
.../marshaller/portable/PortableMarshaller.java | 38 +-
.../ignite/spi/discovery/tcp/ServerImpl.java | 51 +-
.../portable/BinaryFieldsAbstractSelfTest.java | 13 +-
.../BinaryFooterOffsetsAbstractSelfTest.java | 199 +
.../BinaryFooterOffsetsHeapSelfTest.java | 32 +
.../BinaryFooterOffsetsOffheapSelfTest.java | 61 +
.../portable/BinaryMarshallerSelfTest.java | 3795 ++++++++++++++++++
.../BinaryObjectBuilderAdditionalSelfTest.java | 1291 ++++++
.../portable/BinaryObjectBuilderSelfTest.java | 1066 +++++
...idBinaryObjectBuilderAdditionalSelfTest.java | 1280 ------
.../GridBinaryObjectBuilderSelfTest.java | 1053 -----
...idPortableMarshallerCtxDisabledSelfTest.java | 2 +-
.../GridPortableMarshallerSelfTest.java | 3760 -----------------
.../PortableCompactOffsetsAbstractSelfTest.java | 190 -
.../PortableCompactOffsetsHeapSelfTest.java | 32 -
.../PortableCompactOffsetsOffheapSelfTest.java | 61 -
.../BinaryFieldsHeapNonCompactSelfTest.java | 34 +
.../BinaryFieldsOffheapNonCompactSelfTest.java | 30 +
...naryFooterOffsetsHeapNonCompactSelfTest.java | 30 +
...yFooterOffsetsOffheapNonCompactSelfTest.java | 30 +
.../BinaryMarshallerNonCompactSelfTest.java | 30 +
...jectBuilderAdditionalNonCompactSelfTest.java | 30 +
.../BinaryObjectBuilderNonCompactSelfTest.java | 30 +
.../IgnitePortableObjectsTestSuite.java | 36 +-
.../core-test/src/binary_reader_writer_test.cpp | 64 +-
.../include/ignite/impl/binary/binary_common.h | 22 +-
.../ignite/impl/binary/binary_reader_impl.h | 58 +-
.../include/ignite/impl/binary/binary_schema.h | 6 +-
.../ignite/impl/binary/binary_writer_impl.h | 2 +-
.../core/src/impl/binary/binary_reader_impl.cpp | 8 +-
.../cpp/core/src/impl/binary/binary_schema.cpp | 12 +-
.../core/src/impl/binary/binary_writer_impl.cpp | 29 +-
.../Config/Compute/compute-grid1.xml | 1 +
.../Config/marshaller-explicit.xml | 4 +-
.../Impl/Binary/BinaryObjectBuilder.cs | 25 +-
.../Impl/Binary/BinaryObjectHeader.cs | 131 +-
.../Impl/Binary/BinaryObjectSchemaHolder.cs | 9 +-
.../Impl/Binary/BinaryReader.cs | 2 +-
.../Impl/Binary/BinaryWriter.cs | 27 +-
.../Impl/Binary/IgniteBinary.cs | 3 +-
63 files changed, 8154 insertions(+), 7186 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index c4829a4..2b6eaad 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -157,6 +157,7 @@ import org.apache.ignite.lifecycle.LifecycleBean;
import org.apache.ignite.lifecycle.LifecycleEventType;
import org.apache.ignite.marshaller.MarshallerExclusions;
import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
+import org.apache.ignite.marshaller.portable.PortableMarshaller;
import org.apache.ignite.mxbean.ClusterLocalNodeMetricsMXBean;
import org.apache.ignite.mxbean.IgniteMXBean;
import org.apache.ignite.mxbean.ThreadPoolMXBean;
@@ -201,6 +202,7 @@ import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_JVM_PID;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_LANG_RUNTIME;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MACS;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER;
+import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER_COMPACT_FOOTER;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MARSHALLER_USE_DFLT_SUID;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_NODE_CONSISTENT_ID;
import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_PEER_CLASSLOADING;
@@ -1272,6 +1274,10 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
add(ATTR_MARSHALLER, cfg.getMarshaller().getClass().getName());
add(ATTR_MARSHALLER_USE_DFLT_SUID,
getBoolean(IGNITE_OPTIMIZED_MARSHALLER_USE_DEFAULT_SUID, OptimizedMarshaller.USE_DFLT_SUID));
+
+ if (cfg.getMarshaller() instanceof PortableMarshaller)
+ add(ATTR_MARSHALLER_COMPACT_FOOTER, ((PortableMarshaller)cfg.getMarshaller()).isCompactFooter());
+
add(ATTR_USER_NAME, System.getProperty("user.name"));
add(ATTR_GRID_NAME, gridName);
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
index 86a460d..946b686 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteNodeAttributes.java
@@ -36,6 +36,9 @@ public final class IgniteNodeAttributes {
/** Internal attribute name constant. */
public static final String ATTR_MARSHALLER_USE_DFLT_SUID = ATTR_PREFIX + ".marshaller.useDefaultSUID";
+ /** Attribute for marshaller compact footers. */
+ public static final String ATTR_MARSHALLER_COMPACT_FOOTER = ATTR_PREFIX + ".marshaller.compactFooter";
+
/** Internal attribute name constant. */
public static final String ATTR_JIT_NAME = ATTR_PREFIX + ".jit.name";
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryCachingMetadataHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryCachingMetadataHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryCachingMetadataHandler.java
new file mode 100644
index 0000000..a3c846b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryCachingMetadataHandler.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.ignite.internal.portable;
+
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryType;
+
+import java.util.HashMap;
+
+/**
+ * Simple caching metadata handler. Used mainly in tests.
+ */
+public class BinaryCachingMetadataHandler implements BinaryMetadataHandler {
+ /** Cached metadatas. */
+ private final HashMap<Integer, BinaryType> metas = new HashMap<>();
+
+ /**
+ * Create new handler instance.
+ *
+ * @return New handler.
+ */
+ public static BinaryCachingMetadataHandler create() {
+ return new BinaryCachingMetadataHandler();
+ }
+
+ /**
+ * Private constructor.
+ */
+ private BinaryCachingMetadataHandler() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized void addMeta(int typeId, BinaryType type) throws BinaryObjectException {
+ synchronized (this) {
+ BinaryType oldType = metas.put(typeId, type);
+
+ if (oldType != null) {
+ BinaryMetadata oldMeta = ((BinaryTypeImpl)oldType).metadata();
+ BinaryMetadata newMeta = ((BinaryTypeImpl)type).metadata();
+
+ BinaryMetadata mergedMeta = PortableUtils.mergeMetadata(oldMeta, newMeta);
+
+ BinaryType mergedType = mergedMeta.wrap(((BinaryTypeImpl)oldType).context());
+
+ metas.put(typeId, mergedType);
+ }
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public synchronized BinaryType metadata(int typeId) throws BinaryObjectException {
+ return metas.get(typeId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
index fe88d11..a464d6e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadata.java
@@ -49,6 +49,9 @@ public class BinaryMetadata implements Externalizable {
/** Affinity key field name. */
private String affKeyFieldName;
+ /** Schemas associated with type. */
+ private Collection<PortableSchema> schemas;
+
/**
* For {@link Externalizable}.
*/
@@ -63,15 +66,17 @@ public class BinaryMetadata implements Externalizable {
* @param typeName Type name.
* @param fields Fields map.
* @param affKeyFieldName Affinity key field name.
+ * @param schemas Schemas.
*/
public BinaryMetadata(int typeId, String typeName, @Nullable Map<String, Integer> fields,
- @Nullable String affKeyFieldName) {
+ @Nullable String affKeyFieldName, @Nullable Collection<PortableSchema> schemas) {
assert typeName != null;
this.typeId = typeId;
this.typeName = typeName;
this.fields = fields;
this.affKeyFieldName = affKeyFieldName;
+ this.schemas = schemas;
}
/**
@@ -120,6 +125,13 @@ public class BinaryMetadata implements Externalizable {
}
/**
+ * @return Schemas.
+ */
+ public Collection<PortableSchema> schemas() {
+ return schemas != null ? schemas : Collections.<PortableSchema>emptyList();
+ }
+
+ /**
* Wrap metadata into binary type.
*
* @param ctx Portable context.
@@ -135,6 +147,7 @@ public class BinaryMetadata implements Externalizable {
U.writeString(out, typeName);
U.writeMap(out, fields);
U.writeString(out, affKeyFieldName);
+ U.writeCollection(out, schemas);
}
/** {@inheritDoc} */
@@ -143,6 +156,7 @@ public class BinaryMetadata implements Externalizable {
typeName = U.readString(in);
fields = U.readMap(in);
affKeyFieldName = U.readString(in);
+ schemas = U.readCollection(in);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadataCollector.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadataCollector.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadataCollector.java
index 67e1a0d..28eb1d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadataCollector.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryMetadataCollector.java
@@ -17,6 +17,12 @@
package org.apache.ignite.internal.portable;
+import org.apache.ignite.binary.BinaryIdMapper;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.binary.BinaryWriter;
+import org.jetbrains.annotations.Nullable;
+
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -27,26 +33,37 @@ import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.binary.BinaryRawWriter;
-import org.apache.ignite.binary.BinaryWriter;
-import org.jetbrains.annotations.Nullable;
/**
* Writer for meta data collection.
*/
class BinaryMetadataCollector implements BinaryWriter {
- /** */
- private final Map<String, Integer> meta = new HashMap<>();
+ /** Type ID. */
+ private final int typeId;
- /** */
+ /** Type name. */
private final String typeName;
+ /** ID mapper. */
+ private final BinaryIdMapper idMapper;
+
+ /** Collected metadata. */
+ private final Map<String, Integer> meta = new HashMap<>();
+
+ /** Schema builder. */
+ private PortableSchema.Builder schemaBuilder = PortableSchema.Builder.newBuilder();
+
/**
+ * Constructor.
+ *
+ * @param typeId Type ID.
* @param typeName Type name.
+ * @param idMapper ID mapper.
*/
- BinaryMetadataCollector(String typeName) {
+ BinaryMetadataCollector(int typeId, String typeName, BinaryIdMapper idMapper) {
+ this.typeId = typeId;
this.typeName = typeName;
+ this.idMapper = idMapper;
}
/**
@@ -56,6 +73,13 @@ class BinaryMetadataCollector implements BinaryWriter {
return meta;
}
+ /**
+ * @return Schemas.
+ */
+ PortableSchema schema() {
+ return schemaBuilder.build();
+ }
+
/** {@inheritDoc} */
@Override public void writeByte(String fieldName, byte val) throws BinaryObjectException {
add(fieldName, PortableClassDescriptor.Mode.BYTE);
@@ -242,13 +266,12 @@ class BinaryMetadataCollector implements BinaryWriter {
if (oldFieldTypeId != null && !oldFieldTypeId.equals(fieldTypeId)) {
throw new BinaryObjectException(
- "Field is written twice with different types [" +
- "typeName=" + typeName +
- ", fieldName=" + name +
+ "Field is written twice with different types [" + "typeName=" + typeName + ", fieldName=" + name +
", fieldTypeName1=" + PortableUtils.fieldTypeName(oldFieldTypeId) +
- ", fieldTypeName2=" + PortableUtils.fieldTypeName(fieldTypeId) +
- ']'
+ ", fieldTypeName2=" + PortableUtils.fieldTypeName(fieldTypeId) + ']'
);
}
+
+ schemaBuilder.addField(idMapper.fieldId(typeId, name));
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectEx.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectEx.java
index b3512ce..6902675 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectEx.java
@@ -170,7 +170,7 @@ public abstract class BinaryObjectEx implements BinaryObject {
}
if (meta == null)
- return "PortableObject [hash=" + idHash + ", typeId=" + typeId() + ']';
+ return BinaryObject.class.getSimpleName() + " [hash=" + idHash + ", typeId=" + typeId() + ']';
handles.put(this, idHash);
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
index d432ea0..d9339f8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectImpl.java
@@ -251,7 +251,7 @@ public final class BinaryObjectImpl extends BinaryObjectEx implements Externaliz
if (ctx == null)
throw new BinaryObjectException("PortableContext is not set for the object.");
- return ctx.metaData(typeId());
+ return ctx.metadata(typeId());
}
/** {@inheritDoc} */
@@ -279,15 +279,17 @@ public final class BinaryObjectImpl extends BinaryObjectEx implements Externaliz
int schemaOffset = PortablePrimitives.readInt(arr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
short flags = PortablePrimitives.readShort(arr, start + GridPortableMarshaller.FLAGS_POS);
- int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags);
- int fieldOffsetPos = start + schemaOffset + order * (4 + fieldOffsetSize) + 4;
+ int fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
int fieldPos;
- if (fieldOffsetSize == PortableUtils.OFFSET_1)
+ if (fieldOffsetLen == PortableUtils.OFFSET_1)
fieldPos = start + ((int)PortablePrimitives.readByte(arr, fieldOffsetPos) & 0xFF);
- else if (fieldOffsetSize == PortableUtils.OFFSET_2)
+ else if (fieldOffsetLen == PortableUtils.OFFSET_2)
fieldPos = start + ((int)PortablePrimitives.readShort(arr, fieldOffsetPos) & 0xFFFF);
else
fieldPos = start + PortablePrimitives.readInt(arr, fieldOffsetPos);
@@ -458,7 +460,7 @@ public final class BinaryObjectImpl extends BinaryObjectEx implements Externaliz
@Override protected PortableSchema createSchema() {
BinaryReaderExImpl reader = new BinaryReaderExImpl(ctx, arr, start, null);
- return reader.createSchema();
+ return reader.getOrCreateSchema();
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectOffheapImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectOffheapImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectOffheapImpl.java
index f7cb844..a71c98a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectOffheapImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryObjectOffheapImpl.java
@@ -136,7 +136,7 @@ public class BinaryObjectOffheapImpl extends BinaryObjectEx implements Externali
start,
null);
- return reader.createSchema();
+ return reader.getOrCreateSchema();
}
/** {@inheritDoc} */
@@ -164,7 +164,7 @@ public class BinaryObjectOffheapImpl extends BinaryObjectEx implements Externali
if (ctx == null)
throw new BinaryObjectException("PortableContext is not set for the object.");
- return ctx.metaData(typeId());
+ return ctx.metadata(typeId());
}
/** {@inheritDoc} */
@@ -198,15 +198,17 @@ public class BinaryObjectOffheapImpl extends BinaryObjectEx implements Externali
int schemaOffset = PortablePrimitives.readInt(ptr, start + GridPortableMarshaller.SCHEMA_OR_RAW_OFF_POS);
short flags = PortablePrimitives.readShort(ptr, start + GridPortableMarshaller.FLAGS_POS);
- int fieldOffsetSize = PortableUtils.fieldOffsetSize(flags);
- int fieldOffsetPos = start + schemaOffset + order * (4 + fieldOffsetSize) + 4;
+ int fieldIdLen = PortableUtils.isCompactFooter(flags) ? 0 : PortableUtils.FIELD_ID_LEN;
+ int fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
+
+ int fieldOffsetPos = start + schemaOffset + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
int fieldPos;
- if (fieldOffsetSize == PortableUtils.OFFSET_1)
+ if (fieldOffsetLen == PortableUtils.OFFSET_1)
fieldPos = start + ((int)PortablePrimitives.readByte(ptr, fieldOffsetPos) & 0xFF);
- else if (fieldOffsetSize == PortableUtils.OFFSET_2)
+ else if (fieldOffsetLen == PortableUtils.OFFSET_2)
fieldPos = start + ((int)PortablePrimitives.readShort(ptr, fieldOffsetPos) & 0xFFFF);
else
fieldPos = start + PortablePrimitives.readInt(ptr, fieldOffsetPos);
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
index 669ba01..6ff3047 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryReaderExImpl.java
@@ -17,6 +17,23 @@
package org.apache.ignite.internal.portable;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.binary.BinaryIdMapper;
+import org.apache.ignite.binary.BinaryInvalidTypeException;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.binary.BinaryObjectException;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryReader;
+import org.apache.ignite.internal.portable.streams.PortableHeapInputStream;
+import org.apache.ignite.internal.portable.streams.PortableInputStream;
+import org.apache.ignite.internal.util.GridEnumCache;
+import org.apache.ignite.internal.util.lang.GridMapEntry;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
@@ -30,7 +47,6 @@ import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
-import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
@@ -39,22 +55,6 @@ import java.util.TreeSet;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.binary.BinaryObject;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.binary.BinaryIdMapper;
-import org.apache.ignite.binary.BinaryInvalidTypeException;
-import org.apache.ignite.binary.BinaryRawReader;
-import org.apache.ignite.binary.BinaryReader;
-import org.apache.ignite.internal.portable.streams.PortableHeapInputStream;
-import org.apache.ignite.internal.portable.streams.PortableInputStream;
-import org.apache.ignite.internal.util.GridEnumCache;
-import org.apache.ignite.internal.util.lang.GridMapEntry;
-import org.apache.ignite.internal.util.typedef.internal.SB;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiTuple;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.ignite.internal.portable.GridPortableMarshaller.ARR_LIST;
@@ -117,9 +117,6 @@ import static org.apache.ignite.internal.portable.GridPortableMarshaller.UUID_AR
*/
@SuppressWarnings("unchecked")
public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, ObjectInput {
- /** Length of a single field descriptor. */
- private static final int FIELD_DESC_LEN = 16;
-
/** */
private final PortableContext ctx;
@@ -162,8 +159,14 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
/** Schema Id. */
private int schemaId;
+ /** Whether this is user type or not. */
+ private boolean userType;
+
+ /** Whether field IDs exist. */
+ private int fieldIdLen;
+
/** Offset size in bytes. */
- private int offsetSize;
+ private int fieldOffsetLen;
/** Object schema. */
private PortableSchema schema;
@@ -225,18 +228,21 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
short flags = in.readShort();
- offsetSize = PortableUtils.fieldOffsetSize(flags);
+ userType = PortableUtils.isUserType(flags);
+
+ fieldIdLen = PortableUtils.fieldIdLength(flags);
+ fieldOffsetLen = PortableUtils.fieldOffsetLength(flags);
typeId = in.readIntPositioned(start + GridPortableMarshaller.TYPE_ID_POS);
- IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(in, start, offsetSize);
+ IgniteBiTuple<Integer, Integer> footer = PortableUtils.footerAbsolute(in, start);
footerStart = footer.get1();
footerLen = footer.get2() - footerStart;
schemaId = in.readIntPositioned(start + GridPortableMarshaller.SCHEMA_ID_POS);
- rawOff = PortableUtils.rawOffsetAbsolute(in, start, offsetSize);
+ rawOff = PortableUtils.rawOffsetAbsolute(in, start);
if (typeId == UNREGISTERED_TYPE_ID) {
// Skip to the class name position.
@@ -2555,29 +2561,68 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
}
/**
- * Create schema.
+ * Get or create object schema.
*
* @return Schema.
*/
- public PortableSchema createSchema() {
+ public PortableSchema getOrCreateSchema() {
parseHeaderIfNeeded();
- LinkedHashMap<Integer, Integer> fields = new LinkedHashMap<>();
+ PortableSchema schema = ctx.schemaRegistry(typeId).schema(schemaId);
+
+ if (schema == null) {
+ if (fieldIdLen != PortableUtils.FIELD_ID_LEN) {
+ BinaryTypeImpl type = (BinaryTypeImpl)ctx.metadata(typeId);
+
+ if (type == null || type.metadata() == null)
+ throw new BinaryObjectException("Cannot find metadata for object with compact footer: " +
+ typeId);
+
+ for (PortableSchema typeSchema : type.metadata().schemas()) {
+ if (schemaId == typeSchema.schemaId()) {
+ schema = typeSchema;
+
+ break;
+ }
+ }
+
+ if (schema == null)
+ throw new BinaryObjectException("Cannot find schema for object with compact footer [" +
+ "typeId=" + typeId + ", schemaId=" + schemaId + ']');
+ }
+ else
+ schema = createSchema();
+
+ assert schema != null;
+
+ ctx.schemaRegistry(typeId).addSchema(schemaId, schema);
+ }
+
+ return schema;
+ }
+
+ /**
+ * Create schema.
+ *
+ * @return Schema.
+ */
+ private PortableSchema createSchema() {
+ assert fieldIdLen == PortableUtils.FIELD_ID_LEN;
+
+ PortableSchema.Builder builder = PortableSchema.Builder.newBuilder();
int searchPos = footerStart;
int searchEnd = searchPos + footerLen;
- int idx = 0;
-
while (searchPos < searchEnd) {
int fieldId = in.readIntPositioned(searchPos);
- fields.put(fieldId, idx++);
+ builder.addField(fieldId);
- searchPos += 4 + offsetSize;
+ searchPos += PortableUtils.FIELD_ID_LEN + fieldOffsetLen;
}
- return new PortableSchema(fields);
+ return builder.build();
}
/**
@@ -2593,7 +2638,7 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
int searchPos = footerStart;
int searchTail = searchPos + footerLen;
- if (hasLowFieldsCount(footerLen)) {
+ if (!userType || (fieldIdLen != 0 && hasLowFieldsCount(footerLen))) {
while (true) {
if (searchPos >= searchTail)
return 0;
@@ -2601,37 +2646,32 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
int id0 = in.readIntPositioned(searchPos);
if (id0 == id) {
- int pos = start + PortableUtils.fieldOffsetRelative(in, searchPos + 4, offsetSize);
+ int pos = start + PortableUtils.fieldOffsetRelative(in, searchPos + PortableUtils.FIELD_ID_LEN,
+ fieldOffsetLen);
in.position(pos);
return pos;
}
- searchPos += 4 + offsetSize;
+ searchPos += PortableUtils.FIELD_ID_LEN + fieldOffsetLen;
}
}
else {
PortableSchema schema0 = schema;
if (schema0 == null) {
- schema0 = ctx.schemaRegistry(typeId).schema(schemaId);
-
- if (schema0 == null) {
- schema0 = createSchema();
-
- ctx.schemaRegistry(typeId).addSchema(schemaId, schema0);
- }
+ schema0 = getOrCreateSchema();
schema = schema0;
}
- int order = schema.order(id);
+ int order = schema0.order(id);
if (order != PortableSchema.ORDER_NOT_FOUND) {
- int offsetPos = footerStart + order * (4 + offsetSize) + 4;
+ int offsetPos = footerStart + order * (fieldIdLen + fieldOffsetLen) + fieldIdLen;
- int pos = start + PortableUtils.fieldOffsetRelative(in, offsetPos, offsetSize);
+ int pos = start + PortableUtils.fieldOffsetRelative(in, offsetPos, fieldOffsetLen);
in.position(pos);
@@ -2650,7 +2690,7 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
private boolean hasLowFieldsCount(int footerLen) {
assert hdrParsed;
- return footerLen < (FIELD_DESC_LEN << 4);
+ return footerLen < ((fieldOffsetLen + fieldIdLen) << 3);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
index 40b6252..60c135d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryTypeImpl.java
@@ -62,10 +62,15 @@ public class BinaryTypeImpl implements BinaryType {
return ctx.createField(meta.typeId(), fieldName);
}
- public String affinityKeyFieldName() {
+ /** {@inheritDoc} */
+ @Override public String affinityKeyFieldName() {
return meta.affinityKeyFieldName();
}
+ /** {@inheritDoc} */
+ public PortableContext context() {
+ return ctx;
+ }
/**
* @return Metadata.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
index cedf1c8..6cb18fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/BinaryWriterExImpl.java
@@ -90,15 +90,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
/** Length: integer. */
private static final int LEN_INT = 4;
- /** */
+ /** Initial capacity. */
private static final int INIT_CAP = 1024;
- /** FNV1 hash offset basis. */
- private static final int FNV1_OFFSET_BASIS = 0x811C9DC5;
-
- /** FNV1 hash prime. */
- private static final int FNV1_PRIME = 0x01000193;
-
/** Maximum offset which fits in 1 byte. */
private static final int MAX_OFFSET_1 = 1 << 8;
@@ -139,7 +133,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
private SchemaHolder schema;
/** Schema ID. */
- private int schemaId;
+ private int schemaId = PortableUtils.schemaInitialId();
/** Amount of written fields. */
private int fieldCnt;
@@ -332,6 +326,7 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
/**
* Perform post-write activity. This includes:
+ * - writing flags;
* - writing object length;
* - writing schema offset;
* - writing schema to the tail.
@@ -339,7 +334,16 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
* @param userType User type flag.
*/
public void postWrite(boolean userType) {
+ short flags = userType ? PortableUtils.FLAG_USR_TYP : 0;
+
+ boolean useCompactFooter = ctx.isCompactFooter() && userType;
+
+ if (useCompactFooter)
+ flags |= PortableUtils.FLAG_COMPACT_FOOTER;
+
if (schema != null) {
+ flags |= PortableUtils.FLAG_HAS_SCHEMA;
+
// Write schema ID.
out.writeInt(start + SCHEMA_ID_POS, schemaId);
@@ -347,34 +351,35 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, out.position() - start);
// Write the schema.
- int offsetByteCnt = schema.write(this, fieldCnt);
+ int offsetByteCnt = schema.write(this, fieldCnt, useCompactFooter);
+ if (offsetByteCnt == PortableUtils.OFFSET_1)
+ flags |= PortableUtils.FLAG_OFFSET_ONE_BYTE;
+ else if (offsetByteCnt == PortableUtils.OFFSET_2)
+ flags |= PortableUtils.FLAG_OFFSET_TWO_BYTES;
+
// Write raw offset if needed.
- if (rawOffPos != 0)
- out.writeInt(rawOffPos - start);
-
- if (offsetByteCnt == PortableUtils.OFFSET_1) {
- int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_ONE_BYTE;
-
- out.writeShort(start + FLAGS_POS, (short)flags);
- }
- else if (offsetByteCnt == PortableUtils.OFFSET_2) {
- int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_OFFSET_TWO_BYTES;
+ if (rawOffPos != 0) {
+ flags |= PortableUtils.FLAG_HAS_RAW;
- out.writeShort(start + FLAGS_POS, (short)flags);
+ out.writeInt(rawOffPos - start);
}
}
else {
- // Write raw-only flag is needed.
- int flags = (userType ? PortableUtils.FLAG_USR_TYP : 0) | PortableUtils.FLAG_RAW_ONLY;
-
- out.writeShort(start + FLAGS_POS, (short)flags);
+ if (rawOffPos != 0) {
+ // If there are no schema, we are free to write raw offset to schema offset.
+ flags |= PortableUtils.FLAG_HAS_RAW;
- // If there are no schema, we are free to write raw offset to schema offset.
- out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, (rawOffPos == 0 ? out.position() : rawOffPos) - start);
+ out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, rawOffPos - start);
+ }
+ else
+ out.writeInt(start + SCHEMA_OR_RAW_OFF_POS, 0);
}
- // 5. Write length.
+ // Write flags.
+ out.writeShort(start + FLAGS_POS, flags);
+
+ // Write length.
out.writeInt(start + TOTAL_LEN_POS, out.position() - start);
}
@@ -1737,22 +1742,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
SCHEMA.set(schema);
}
-
- // Initialize offset when the first field is written.
- schemaId = FNV1_OFFSET_BASIS;
}
- // Advance schema hash.
- int schemaId0 = schemaId ^ (fieldId & 0xFF);
- schemaId0 = schemaId0 * FNV1_PRIME;
- schemaId0 = schemaId0 ^ ((fieldId >> 8) & 0xFF);
- schemaId0 = schemaId0 * FNV1_PRIME;
- schemaId0 = schemaId0 ^ ((fieldId >> 16) & 0xFF);
- schemaId0 = schemaId0 * FNV1_PRIME;
- schemaId0 = schemaId0 ^ ((fieldId >> 24) & 0xFF);
- schemaId0 = schemaId0 * FNV1_PRIME;
-
- schemaId = schemaId0;
+ schemaId = PortableUtils.updateSchemaId(schemaId, fieldId);
schema.push(fieldId, fieldOff);
@@ -1760,6 +1752,25 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
}
/**
+ * @return Current schema ID.
+ */
+ public int schemaId() {
+ return schemaId;
+ }
+
+ /**
+ * @return Current writer's schema.
+ */
+ public PortableSchema currentSchema() {
+ PortableSchema.Builder builder = PortableSchema.Builder.newBuilder();
+
+ if (schema != null)
+ schema.build(builder, fieldCnt);
+
+ return builder.build();
+ }
+
+ /**
* Attempts to write the object as a handle.
*
* @param obj Object to write.
@@ -1844,13 +1855,25 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
}
/**
+ * Build the schema.
+ *
+ * @param builder Builder.
+ * @param fieldCnt Fields count.
+ */
+ public void build(PortableSchema.Builder builder, int fieldCnt) {
+ for (int curIdx = idx - fieldCnt * 2; curIdx < idx; curIdx += 2)
+ builder.addField(data[curIdx]);
+ }
+
+ /**
* Write collected frames and pop them.
*
* @param writer Writer.
* @param fieldCnt Count.
- * @return Amount of bytes dedicated to
+ * @param compactFooter Whether footer should be written in compact form.
+ * @return Amount of bytes dedicated to each field offset. Could be 1, 2 or 4.
*/
- public int write(BinaryWriterExImpl writer, int fieldCnt) {
+ public int write(BinaryWriterExImpl writer, int fieldCnt, boolean compactFooter) {
int startIdx = idx - fieldCnt * 2;
assert startIdx >= 0;
@@ -1859,29 +1882,51 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
int res;
- if (lastOffset < MAX_OFFSET_1) {
- for (int idx0 = startIdx; idx0 < idx; ) {
- writer.writeInt(data[idx0++]);
- writer.writeByte((byte) data[idx0++]);
+ if (compactFooter) {
+ if (lastOffset < MAX_OFFSET_1) {
+ for (int curIdx = startIdx + 1; curIdx < idx; curIdx += 2)
+ writer.writeByte((byte)data[curIdx]);
+
+ res = PortableUtils.OFFSET_1;
}
+ else if (lastOffset < MAX_OFFSET_2) {
+ for (int curIdx = startIdx + 1; curIdx < idx; curIdx += 2)
+ writer.writeShort((short)data[curIdx]);
- res = PortableUtils.OFFSET_1;
- }
- else if (lastOffset < MAX_OFFSET_2) {
- for (int idx0 = startIdx; idx0 < idx; ) {
- writer.writeInt(data[idx0++]);
- writer.writeShort((short)data[idx0++]);
+ res = PortableUtils.OFFSET_2;
}
+ else {
+ for (int curIdx = startIdx + 1; curIdx < idx; curIdx += 2)
+ writer.writeInt(data[curIdx]);
- res = PortableUtils.OFFSET_2;
+ res = PortableUtils.OFFSET_4;
+ }
}
else {
- for (int idx0 = startIdx; idx0 < idx; ) {
- writer.writeInt(data[idx0++]);
- writer.writeInt(data[idx0++]);
+ if (lastOffset < MAX_OFFSET_1) {
+ for (int curIdx = startIdx; curIdx < idx;) {
+ writer.writeInt(data[curIdx++]);
+ writer.writeByte((byte) data[curIdx++]);
+ }
+
+ res = PortableUtils.OFFSET_1;
+ }
+ else if (lastOffset < MAX_OFFSET_2) {
+ for (int curIdx = startIdx; curIdx < idx;) {
+ writer.writeInt(data[curIdx++]);
+ writer.writeShort((short)data[curIdx++]);
+ }
+
+ res = PortableUtils.OFFSET_2;
}
+ else {
+ for (int curIdx = startIdx; curIdx < idx;) {
+ writer.writeInt(data[curIdx++]);
+ writer.writeInt(data[curIdx++]);
+ }
- res = PortableUtils.OFFSET_4;
+ res = PortableUtils.OFFSET_4;
+ }
}
return res;
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
index 225e0ba..8543ce6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableClassDescriptor.java
@@ -38,6 +38,7 @@ import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -79,6 +80,9 @@ public class PortableClassDescriptor {
/** */
private final String typeName;
+ /** Affinity key field name. */
+ private final String affKeyFieldName;
+
/** */
private final Constructor<?> ctor;
@@ -92,7 +96,13 @@ public class PortableClassDescriptor {
private final Method readResolveMtd;
/** */
- private final Map<String, Integer> fieldsMeta;
+ private final Map<String, Integer> stableFieldsMeta;
+
+ /** Object schemas. Initialized only for serializable classes and contains only 1 entry. */
+ private final Collection<PortableSchema> stableSchemas;
+
+ /** Schema registry. */
+ private final PortableSchemaRegistry schemaReg;
/** */
private final boolean keepDeserialized;
@@ -112,13 +122,14 @@ public class PortableClassDescriptor {
* @param userType User type flag.
* @param typeId Type ID.
* @param typeName Type name.
+ * @param affKeyFieldName Affinity key field name.
* @param idMapper ID mapper.
* @param serializer Serializer.
* @param metaDataEnabled Metadata enabled flag.
* @param keepDeserialized Keep deserialized flag.
* @param registered Whether typeId has been successfully registered by MarshallerContext or not.
* @param predefined Whether the class is predefined or not.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @throws BinaryObjectException In case of error.
*/
PortableClassDescriptor(
PortableContext ctx,
@@ -126,6 +137,7 @@ public class PortableClassDescriptor {
boolean userType,
int typeId,
String typeName,
+ @Nullable String affKeyFieldName,
@Nullable BinaryIdMapper idMapper,
@Nullable BinarySerializer serializer,
boolean metaDataEnabled,
@@ -135,17 +147,21 @@ public class PortableClassDescriptor {
) throws BinaryObjectException {
assert ctx != null;
assert cls != null;
+ assert idMapper != null;
this.ctx = ctx;
this.cls = cls;
- this.userType = userType;
this.typeId = typeId;
+ this.userType = userType;
this.typeName = typeName;
+ this.affKeyFieldName = affKeyFieldName;
this.serializer = serializer;
this.idMapper = idMapper;
this.keepDeserialized = keepDeserialized;
this.registered = registered;
+ schemaReg = ctx.schemaRegistry(typeId);
+
excluded = MarshallerExclusions.isExcluded(cls);
useOptMarshaller = !predefined && initUseOptimizedMarshallerFlag();
@@ -193,7 +209,8 @@ public class PortableClassDescriptor {
case EXCLUSION:
ctor = null;
fields = null;
- fieldsMeta = null;
+ stableFieldsMeta = null;
+ stableSchemas = null;
break;
@@ -201,16 +218,17 @@ public class PortableClassDescriptor {
case EXTERNALIZABLE:
ctor = constructor(cls);
fields = null;
- fieldsMeta = null;
+ stableFieldsMeta = null;
+ stableSchemas = null;
break;
case OBJECT:
- assert idMapper != null;
-
ctor = constructor(cls);
fields = new ArrayList<>();
- fieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null;
+ stableFieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null;
+
+ PortableSchema.Builder schemaBuilder = PortableSchema.Builder.newBuilder();
Collection<String> names = new HashSet<>();
Collection<Integer> ids = new HashSet<>();
@@ -236,12 +254,16 @@ public class PortableClassDescriptor {
fields.add(fieldInfo);
+ schemaBuilder.addField(fieldId);
+
if (metaDataEnabled)
- fieldsMeta.put(name, fieldInfo.fieldMode().typeId());
+ stableFieldsMeta.put(name, fieldInfo.fieldMode().typeId());
}
}
}
+ stableSchemas = Collections.singleton(schemaBuilder.build());
+
break;
default:
@@ -284,7 +306,14 @@ public class PortableClassDescriptor {
* @return Fields meta data.
*/
Map<String, Integer> fieldsMeta() {
- return fieldsMeta;
+ return stableFieldsMeta;
+ }
+
+ /**
+ * @return Schemas.
+ */
+ Collection<PortableSchema> schemas() {
+ return stableSchemas;
}
/**
@@ -345,7 +374,7 @@ public class PortableClassDescriptor {
/**
* @param obj Object.
* @param writer Writer.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @throws BinaryObjectException In case of error.
*/
void write(Object obj, BinaryWriterExImpl writer) throws BinaryObjectException {
assert obj != null;
@@ -539,21 +568,34 @@ public class PortableClassDescriptor {
((Binarylizable)obj).writeBinary(writer);
writer.postWrite(userType);
- }
- finally {
- writer.popSchema();
- }
- if (obj.getClass() != BinaryMetadata.class
- && ctx.isMetaDataChanged(typeId, writer.metaDataHashSum())) {
- BinaryMetadataCollector metaCollector = new BinaryMetadataCollector(typeName);
+ // Check whether we need to update metadata.
+ if (obj.getClass() != BinaryMetadata.class) {
+ int schemaId = writer.schemaId();
- if (serializer != null)
- serializer.writeBinary(obj, metaCollector);
- else
- ((Binarylizable)obj).writeBinary(metaCollector);
+ if (schemaReg.schema(schemaId) == null) {
+ // This is new schema, let's update metadata.
+ BinaryMetadataCollector collector =
+ new BinaryMetadataCollector(typeId, typeName, idMapper);
+
+ if (serializer != null)
+ serializer.writeBinary(obj, collector);
+ else
+ ((Binarylizable)obj).writeBinary(collector);
+
+ PortableSchema newSchema = collector.schema();
- ctx.updateMetaData(typeId, typeName, metaCollector.meta());
+ BinaryMetadata meta = new BinaryMetadata(typeId, typeName, collector.meta(),
+ affKeyFieldName, Collections.singleton(newSchema));
+
+ ctx.updateMetadata(typeId, meta);
+
+ schemaReg.addSchema(newSchema.schemaId(), newSchema);
+ }
+ }
+ }
+ finally {
+ writer.popSchema();
}
}
@@ -601,7 +643,7 @@ public class PortableClassDescriptor {
/**
* @param reader Reader.
* @return Object.
- * @throws org.apache.ignite.binary.BinaryObjectException If failed.
+ * @throws BinaryObjectException If failed.
*/
Object read(BinaryReaderExImpl reader) throws BinaryObjectException {
assert reader != null;
@@ -683,7 +725,6 @@ public class PortableClassDescriptor {
PortableUtils.writeHeader(
writer,
- userType,
registered ? typeId : GridPortableMarshaller.UNREGISTERED_TYPE_ID,
obj instanceof CacheObjectImpl ? 0 : obj.hashCode(),
registered ? null : cls.getName()
@@ -694,7 +735,7 @@ public class PortableClassDescriptor {
/**
* @return Instance.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @throws BinaryObjectException In case of error.
*/
private Object newInstance() throws BinaryObjectException {
assert ctor != null;
@@ -710,7 +751,7 @@ public class PortableClassDescriptor {
/**
* @param cls Class.
* @return Constructor.
- * @throws org.apache.ignite.binary.BinaryObjectException If constructor doesn't exist.
+ * @throws BinaryObjectException If constructor doesn't exist.
*/
@SuppressWarnings("ConstantConditions")
@Nullable private static Constructor<?> constructor(Class<?> cls) throws BinaryObjectException {
@@ -719,6 +760,9 @@ public class PortableClassDescriptor {
try {
Constructor<?> ctor = U.forceEmptyConstructor(cls);
+ if (ctor == null)
+ throw new BinaryObjectException("Failed to find empty constructor for class: " + cls.getName());
+
ctor.setAccessible(true);
return ctor;
@@ -871,7 +915,7 @@ public class PortableClassDescriptor {
/**
* @param obj Object.
* @param writer Writer.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @throws BinaryObjectException In case of error.
*/
public void write(Object obj, BinaryWriterExImpl writer) throws BinaryObjectException {
assert obj != null;
@@ -1074,7 +1118,7 @@ public class PortableClassDescriptor {
/**
* @param obj Object.
* @param reader Reader.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @throws BinaryObjectException In case of error.
*/
public void read(Object obj, BinaryReaderExImpl reader) throws BinaryObjectException {
Object val = null;
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
index 86578ad..afc23e1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableContext.java
@@ -61,7 +61,6 @@ import org.apache.ignite.binary.BinarySerializer;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.IgnitionEx;
import org.apache.ignite.internal.processors.cache.portable.CacheObjectBinaryProcessorImpl;
-import org.apache.ignite.internal.util.GridConcurrentHashSet;
import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.internal.util.lang.GridMapEntry;
import org.apache.ignite.internal.util.typedef.F;
@@ -107,9 +106,6 @@ public class PortableContext implements Externalizable {
}
/** */
- private final ConcurrentMap<Integer, Collection<Integer>> metaDataCache = new ConcurrentHashMap8<>();
-
- /** */
private final ConcurrentMap<Class<?>, PortableClassDescriptor> descByCls = new ConcurrentHashMap8<>();
/** Holds classes loaded by default class loader only. */
@@ -130,6 +126,9 @@ public class PortableContext implements Externalizable {
/** */
private final ConcurrentMap<Integer, BinaryIdMapper> mappers = new ConcurrentHashMap8<>(0);
+ /** Affinity key field names. */
+ private final ConcurrentMap<Integer, String> affKeyFieldNames = new ConcurrentHashMap8<>(0);
+
/** */
private final Map<String, BinaryIdMapper> typeMappers = new ConcurrentHashMap8<>(0);
@@ -151,6 +150,9 @@ public class PortableContext implements Externalizable {
/** */
private boolean keepDeserialized;
+ /** Compact footer flag. */
+ private boolean compactFooter;
+
/** Object schemas. */
private volatile Map<Integer, PortableSchemaRegistry> schemas;
@@ -262,6 +264,8 @@ public class PortableContext implements Externalizable {
marsh.getClassNames(),
marsh.getTypeConfigurations()
);
+
+ compactFooter = marsh.isCompactFooter();
}
/**
@@ -504,6 +508,7 @@ public class PortableContext implements Externalizable {
false,
clsName.hashCode(),
clsName,
+ null,
BASIC_CLS_ID_MAPPER,
null,
false,
@@ -550,6 +555,7 @@ public class PortableContext implements Externalizable {
true,
typeId,
typeName,
+ null,
idMapper,
null,
true,
@@ -567,7 +573,8 @@ public class PortableContext implements Externalizable {
mappers.putIfAbsent(typeId, idMapper);
- metaHnd.addMeta(typeId, new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), null).wrap(this));
+ metaHnd.addMeta(typeId,
+ new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), null, desc.schemas()).wrap(this));
return desc;
}
@@ -694,6 +701,7 @@ public class PortableContext implements Externalizable {
false,
id,
typeName,
+ null,
DFLT_ID_MAPPER,
null,
false,
@@ -745,11 +753,17 @@ public class PortableContext implements Externalizable {
if (mappers.put(id, idMapper) != null)
throw new BinaryObjectException("Duplicate type ID [clsName=" + clsName + ", id=" + id + ']');
+ if (affKeyFieldName != null) {
+ if (affKeyFieldNames.put(id, affKeyFieldName) != null)
+ throw new BinaryObjectException("Duplicate type ID [clsName=" + clsName + ", id=" + id + ']');
+ }
+
String typeName = typeName(clsName);
typeMappers.put(typeName, idMapper);
Map<String, Integer> fieldsMeta = null;
+ Collection<PortableSchema> schemas = null;
if (cls != null) {
PortableClassDescriptor desc = new PortableClassDescriptor(
@@ -758,6 +772,7 @@ public class PortableContext implements Externalizable {
true,
id,
typeName,
+ affKeyFieldName,
idMapper,
serializer,
true,
@@ -767,6 +782,7 @@ public class PortableContext implements Externalizable {
);
fieldsMeta = desc.fieldsMeta();
+ schemas = desc.schemas();
if (IgniteUtils.detectClassLoader(cls).equals(dfltLdr))
userTypes.put(id, desc);
@@ -774,7 +790,7 @@ public class PortableContext implements Externalizable {
descByCls.put(cls, desc);
}
- metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName).wrap(this));
+ metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, schemas).wrap(this));
}
/**
@@ -797,48 +813,32 @@ public class PortableContext implements Externalizable {
* @return Meta data.
* @throws org.apache.ignite.binary.BinaryObjectException In case of error.
*/
- @Nullable public BinaryType metaData(int typeId) throws BinaryObjectException {
+ @Nullable public BinaryType metadata(int typeId) throws BinaryObjectException {
return metaHnd != null ? metaHnd.metadata(typeId) : null;
}
/**
* @param typeId Type ID.
- * @param metaHashSum Meta data hash sum.
- * @return Whether meta is changed.
+ * @return Affinity key field name.
*/
- boolean isMetaDataChanged(int typeId, @Nullable Integer metaHashSum) {
- if (metaHashSum == null)
- return false;
-
- Collection<Integer> hist = metaDataCache.get(typeId);
-
- if (hist == null) {
- Collection<Integer> old = metaDataCache.putIfAbsent(typeId, hist = new GridConcurrentHashSet<>());
-
- if (old != null)
- hist = old;
- }
-
- return hist.add(metaHashSum);
+ public String affinityKeyFieldName(int typeId) {
+ return affKeyFieldNames.get(typeId);
}
/**
* @param typeId Type ID.
- * @param typeName Type name.
- * @param fields Fields map.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @param meta Meta data.
+ * @throws BinaryObjectException In case of error.
*/
- public void updateMetaData(int typeId, String typeName, Map<String, Integer> fields) throws BinaryObjectException {
- updateMetaData(typeId, new BinaryMetadata(typeId, typeName, fields, null));
+ public void updateMetadata(int typeId, BinaryMetadata meta) throws BinaryObjectException {
+ metaHnd.addMeta(typeId, meta.wrap(this));
}
/**
- * @param typeId Type ID.
- * @param meta Meta data.
- * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+ * @return Whether field IDs should be skipped in footer or not.
*/
- public void updateMetaData(int typeId, BinaryMetadata meta) throws BinaryObjectException {
- metaHnd.addMeta(typeId, meta.wrap(this));
+ public boolean isCompactFooter() {
+ return compactFooter;
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/0b4a8f83/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
index 96a93f4..86ca5f8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableSchema.java
@@ -17,10 +17,16 @@
package org.apache.ignite.internal.portable;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.List;
/**
* Schema describing portable object content. We rely on the following assumptions:
@@ -28,130 +34,150 @@ import java.util.Map;
* for quick comparisons performed within already fetched L1 cache line.
* - When there are more fields, we store them inside a hash map.
*/
-public class PortableSchema {
+public class PortableSchema implements Externalizable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
/** Order returned if field is not found. */
public static final int ORDER_NOT_FOUND = -1;
/** Inline flag. */
- private final boolean inline;
+ private boolean inline;
+
+ /** Map with ID to order. */
+ private HashMap<Integer, Integer> idToOrder;
- /** Map with offsets. */
- private final HashMap<Integer, Integer> map;
+ /** IDs depending on order. */
+ private ArrayList<Integer> ids;
/** ID 1. */
- private final int id0;
+ private int id0;
/** ID 2. */
- private final int id1;
+ private int id1;
/** ID 3. */
- private final int id2;
+ private int id2;
/** ID 4. */
- private final int id3;
+ private int id3;
/** ID 1. */
- private final int id4;
+ private int id4;
/** ID 2. */
- private final int id5;
+ private int id5;
/** ID 3. */
- private final int id6;
+ private int id6;
/** ID 4. */
- private final int id7;
+ private int id7;
+
+ /** Schema ID. */
+ private int schemaId;
+
+ /**
+ * {@link Externalizable} support.
+ */
+ public PortableSchema() {
+ // No-op.
+ }
/**
* Constructor.
*
- * @param vals Values.
+ * @param schemaId Schema ID.
+ * @param fieldIds Field IDs.
*/
- public PortableSchema(LinkedHashMap<Integer, Integer> vals) {
- if (vals.size() <= 8) {
- inline = true;
-
- Iterator<Map.Entry<Integer, Integer>> iter = vals.entrySet().iterator();
+ private PortableSchema(int schemaId, List<Integer> fieldIds) {
+ this.schemaId = schemaId;
- Map.Entry<Integer, Integer> entry = iter.hasNext() ? iter.next() : null;
-
- if (entry != null) {
- id0 = entry.getKey();
+ if (fieldIds.size() <= 8) {
+ inline = true;
- assert entry.getValue() == 0;
- }
- else
- id0 = 0;
+ Iterator<Integer> iter = fieldIds.iterator();
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id1 = entry.getKey();
+ id0 = iter.hasNext() ? iter.next() : 0;
+ id1 = iter.hasNext() ? iter.next() : 0;
+ id2 = iter.hasNext() ? iter.next() : 0;
+ id3 = iter.hasNext() ? iter.next() : 0;
+ id4 = iter.hasNext() ? iter.next() : 0;
+ id5 = iter.hasNext() ? iter.next() : 0;
+ id6 = iter.hasNext() ? iter.next() : 0;
+ id7 = iter.hasNext() ? iter.next() : 0;
- assert entry.getValue() == 1;
- }
- else
- id1 = 0;
+ idToOrder = null;
+ }
+ else {
+ inline = false;
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id2 = entry.getKey();
+ id0 = id1 = id2 = id3 = id4 = id5 = id6 = id7 = 0;
- assert entry.getValue() == 2;
- }
- else
- id2 = 0;
+ ids = new ArrayList<>();
+ idToOrder = new HashMap<>();
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id3 = entry.getKey();
+ for (int i = 0; i < fieldIds.size(); i++) {
+ int fieldId = fieldIds.get(i);
- assert entry.getValue() == 3;
+ ids.add(fieldId);
+ idToOrder.put(fieldId, i);
}
- else
- id3 = 0;
+ }
+ }
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id4 = entry.getKey();
+ /**
+ * @return Schema ID.
+ */
+ public int schemaId() {
+ return schemaId;
+ }
- assert entry.getValue() == 4;
- }
- else
- id4 = 0;
+ /**
+ * Get field ID by order in footer.
+ *
+ * @param order Order.
+ * @return Field ID.
+ */
+ public int fieldId(int order) {
+ if (inline) {
+ switch (order) {
+ case 0:
+ return id0;
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id5 = entry.getKey();
+ case 1:
+ return id1;
- assert entry.getValue() == 5;
- }
- else
- id5 = 0;
+ case 2:
+ return id2;
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id6 = entry.getKey();
+ case 3:
+ return id3;
- assert entry.getValue() == 6;
- }
- else
- id6 = 0;
+ case 4:
+ return id4;
- if ((entry = iter.hasNext() ? iter.next() : null) != null) {
- id7 = entry.getKey();
+ case 5:
+ return id5;
- assert entry.getValue() == 7;
- }
- else
- id7 = 0;
+ case 6:
+ return id6;
- map = null;
- }
- else {
- inline = false;
+ case 7:
+ return id7;
- id0 = id1 = id2 = id3 = id4 = id5 = id6 = id7 = 0;
+ default:
+ assert false : "Should not reach here.";
- map = new HashMap<>(vals);
+ return 0;
+ }
}
+ else
+ return ids.get(order);
}
/**
- * Get field position in footer by schema ID.
+ * Get field order in footer by field ID.
*
* @param id Field ID.
* @return Offset or {@code 0} if there is no such field.
@@ -185,9 +211,125 @@ public class PortableSchema {
return ORDER_NOT_FOUND;
}
else {
- Integer order = map.get(id);
+ Integer order = idToOrder.get(id);
return order != null ? order : ORDER_NOT_FOUND;
}
}
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return schemaId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ return o != null && o instanceof PortableSchema && schemaId == ((PortableSchema)o).schemaId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeInt(schemaId);
+
+ if (inline) {
+ out.writeBoolean(true);
+
+ out.writeInt(id0);
+ out.writeInt(id1);
+ out.writeInt(id2);
+ out.writeInt(id3);
+ out.writeInt(id4);
+ out.writeInt(id5);
+ out.writeInt(id6);
+ out.writeInt(id7);
+ }
+ else {
+ out.writeBoolean(false);
+
+ out.writeInt(ids.size());
+
+ for (Integer id : ids)
+ out.writeInt(id);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ schemaId = in.readInt();
+
+ if (in.readBoolean()) {
+ inline = true;
+
+ id0 = in.readInt();
+ id1 = in.readInt();
+ id2 = in.readInt();
+ id3 = in.readInt();
+ id4 = in.readInt();
+ id5 = in.readInt();
+ id6 = in.readInt();
+ id7 = in.readInt();
+ }
+ else {
+ inline = false;
+
+ int size = in.readInt();
+
+ ids = new ArrayList<>(size);
+ idToOrder = U.newHashMap(size);
+
+ for (int i = 0; i < size; i++) {
+ int fieldId = in.readInt();
+
+ ids.add(fieldId);
+ idToOrder.put(fieldId, i);
+ }
+ }
+ }
+
+ /**
+ * Schema builder.
+ */
+ public static class Builder {
+ /** Schema ID. */
+ private int schemaId = PortableUtils.schemaInitialId();
+
+ /** Fields. */
+ private final ArrayList<Integer> fields = new ArrayList<>();
+
+ /**
+ * Create new schema builder.
+ *
+ * @return Schema builder.
+ */
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ /**
+ * Private constructor.
+ */
+ private Builder() {
+ // No-op.
+ }
+
+ /**
+ * Add field.
+ *
+ * @param fieldId Field ID.
+ */
+ public void addField(int fieldId) {
+ fields.add(fieldId);
+
+ schemaId = PortableUtils.updateSchemaId(schemaId, fieldId);
+ }
+
+ /**
+ * Build schema.
+ *
+ * @return Schema.
+ */
+ public PortableSchema build() {
+ return new PortableSchema(schemaId, fields);
+ }
+ }
}