You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/11/11 14:17:38 UTC

[1/3] ignite git commit: IGNITE-1816: WIP.

Repository: ignite
Updated Branches:
  refs/heads/ignite-1816 3629a3e48 -> ed3472d4e


IGNITE-1816: WIP.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9e792606
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9e792606
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9e792606

Branch: refs/heads/ignite-1816
Commit: 9e792606357fd7fd174a4bc934c3871c6f9ceb96
Parents: 3629a3e
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Nov 11 13:28:20 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Nov 11 13:28:20 2015 +0300

----------------------------------------------------------------------
 .../internal/portable/BinaryMetadata.java       |  16 +-
 .../internal/portable/BinaryReaderExImpl.java   |  42 ++--
 .../internal/portable/BinaryWriterExImpl.java   |  43 ++--
 .../portable/PortableClassDescriptor.java       |  21 +-
 .../internal/portable/PortableContext.java      |  26 ++-
 .../internal/portable/PortableSchema.java       | 156 +++++++------
 .../ignite/internal/portable/PortableUtils.java | 226 ++++++++++---------
 .../builder/BinaryObjectBuilderImpl.java        |   2 +-
 .../CacheObjectBinaryProcessorImpl.java         |   6 +-
 .../marshaller/portable/PortableMarshaller.java |   2 +-
 10 files changed, 297 insertions(+), 243 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/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..e7eb70f 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.
+     */
+    @Nullable public Collection<PortableSchema> schemas() {
+        return schemas;
+    }
+
+    /**
      * 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/9e792606/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 1fbdef5..ff33d08 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;
@@ -2565,22 +2565,20 @@ public class BinaryReaderExImpl implements BinaryReader, BinaryRawReaderEx, Obje
 
         assert fieldIdLen == PortableUtils.FIELD_ID_LEN;
 
-        LinkedHashMap<Integer, Integer> fields = new LinkedHashMap<>();
+        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 += PortableUtils.FIELD_ID_LEN + fieldOffsetLen;
         }
 
-        return new PortableSchema(fields);
+        return builder.build();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/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 f1ecb0f..5a48833 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
@@ -93,12 +93,6 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
     /** 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;
 
@@ -342,8 +336,8 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
     public void postWrite(boolean userType) {
         short flags = userType ? PortableUtils.FLAG_USR_TYP : 0;
 
-        if (ctx.isNoFieldIds())
-            flags |= PortableUtils.FLAG_NO_FIELD_IDS;
+        if (ctx.isCompactFooter())
+            flags |= PortableUtils.FLAG_COMPACT_FOOTER;
 
         if (schema != null) {
             // Write schema ID.
@@ -353,7 +347,7 @@ 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, !ctx.isCompactFooter());
 
             // Write raw offset if needed.
             if (rawOffPos != 0)
@@ -1740,20 +1734,10 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
             }
 
             // Initialize offset when the first field is written.
-            schemaId = FNV1_OFFSET_BASIS;
+            schemaId = PortableUtils.schemaInitialId();
         }
 
-        // 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);
 
@@ -1849,9 +1833,10 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
          *
          * @param writer Writer.
          * @param fieldCnt Count.
-         * @return Amount of bytes dedicated to
+         * @param writeFieldId Whether to write field IDs.
+         * @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 writeFieldId) {
             int startIdx = idx - fieldCnt * 2;
 
             assert startIdx >= 0;
@@ -1862,7 +1847,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
 
             if (lastOffset < MAX_OFFSET_1) {
                 for (int idx0 = startIdx; idx0 < idx; ) {
-                    writer.writeInt(data[idx0++]);
+                    if (writeFieldId)
+                        writer.writeInt(data[idx0++]);
+
                     writer.writeByte((byte) data[idx0++]);
                 }
 
@@ -1870,7 +1857,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
             }
             else if (lastOffset < MAX_OFFSET_2) {
                 for (int idx0 = startIdx; idx0 < idx; ) {
-                    writer.writeInt(data[idx0++]);
+                    if (writeFieldId)
+                        writer.writeInt(data[idx0++]);
+
                     writer.writeShort((short)data[idx0++]);
                 }
 
@@ -1878,7 +1867,9 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
             }
             else {
                 for (int idx0 = startIdx; idx0 < idx; ) {
-                    writer.writeInt(data[idx0++]);
+                    if (writeFieldId)
+                        writer.writeInt(data[idx0++]);
+
                     writer.writeInt(data[idx0++]);
                 }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/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 7ab662a..361c754 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;
@@ -94,6 +95,9 @@ public class PortableClassDescriptor {
     /** */
     private final Map<String, Integer> fieldsMeta;
 
+    /** Object schemas. Initialized only for serializable classes and contains only 1 entry. */
+    private final Collection<PortableSchema> schemas;
+
     /** */
     private final boolean keepDeserialized;
 
@@ -194,6 +198,7 @@ public class PortableClassDescriptor {
                 ctor = null;
                 fields = null;
                 fieldsMeta = null;
+                schemas = null;
 
                 break;
 
@@ -202,6 +207,7 @@ public class PortableClassDescriptor {
                 ctor = constructor(cls);
                 fields = null;
                 fieldsMeta = null;
+                schemas = null;
 
                 break;
 
@@ -212,6 +218,8 @@ public class PortableClassDescriptor {
                 fields = new ArrayList<>();
                 fieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null;
 
+                PortableSchema.Builder schemaBuilder = PortableSchema.Builder.newBuilder();
+
                 Collection<String> names = new HashSet<>();
                 Collection<Integer> ids = new HashSet<>();
 
@@ -236,12 +244,16 @@ public class PortableClassDescriptor {
 
                             fields.add(fieldInfo);
 
+                            schemaBuilder.addField(fieldId);
+
                             if (metaDataEnabled)
                                 fieldsMeta.put(name, fieldInfo.fieldMode().typeId());
                         }
                     }
                 }
 
+                schemas = Collections.singleton(schemaBuilder.build());
+
                 break;
 
             default:
@@ -288,6 +300,13 @@ public class PortableClassDescriptor {
     }
 
     /**
+     * @return Schemas.
+     */
+    Collection<PortableSchema> schemas() {
+        return schemas;
+    }
+
+    /**
      * @return Keep deserialized flag.
      */
     boolean keepDeserialized() {
@@ -553,7 +572,7 @@ public class PortableClassDescriptor {
                         else
                             ((Binarylizable)obj).writeBinary(metaCollector);
 
-                        ctx.updateMetaData(typeId, typeName, metaCollector.meta());
+                        ctx.updateMetadata(typeId, typeName, metaCollector.meta());
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/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 8b51985..939faa0 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
@@ -151,6 +151,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 +265,8 @@ public class PortableContext implements Externalizable {
             marsh.getClassNames(),
             marsh.getTypeConfigurations()
         );
+
+        compactFooter = marsh.isCompactFooter();
     }
 
     /**
@@ -567,7 +572,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;
     }
@@ -750,6 +756,7 @@ public class PortableContext implements Externalizable {
         typeMappers.put(typeName, idMapper);
 
         Map<String, Integer> fieldsMeta = null;
+        Collection<PortableSchema> schemas = null;
 
         if (cls != null) {
             PortableClassDescriptor desc = new PortableClassDescriptor(
@@ -767,6 +774,7 @@ public class PortableContext implements Externalizable {
             );
 
             fieldsMeta = desc.fieldsMeta();
+            schemas = desc.schemas();
 
             if (IgniteUtils.detectClassLoader(cls).equals(dfltLdr))
                 userTypes.put(id, desc);
@@ -774,7 +782,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));
     }
 
     /**
@@ -826,26 +834,26 @@ public class PortableContext implements Externalizable {
      * @param typeId Type ID.
      * @param typeName Type name.
      * @param fields Fields map.
-     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+     * @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, String typeName, Map<String, Integer> fields) throws BinaryObjectException {
+        updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fields, null, null));
     }
 
     /**
      * @param typeId Type ID.
      * @param meta Meta data.
-     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+     * @throws BinaryObjectException In case of error.
      */
-    public void updateMetaData(int typeId, BinaryMetadata meta) throws BinaryObjectException {
+    public void updateMetadata(int typeId, BinaryMetadata meta) throws BinaryObjectException {
         metaHnd.addMeta(typeId, meta.wrap(this));
     }
 
     /**
      * @return Whether field IDs should be skipped in footer or not.
      */
-    public boolean isNoFieldIds() {
-        return false; // TODO: IGNITE-1816: Take from config.
+    public boolean isCompactFooter() {
+        return compactFooter;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/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..a670b78 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,11 @@
 
 package org.apache.ignite.internal.portable;
 
+import java.io.Serializable;
+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,7 +29,10 @@ 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 Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
     /** Order returned if field is not found. */
     public static final int ORDER_NOT_FOUND = -1;
 
@@ -62,82 +66,31 @@ public class PortableSchema {
     /** ID 4. */
     private final int id7;
 
+    /** Schema ID. */
+    private final int schemaId;
+
     /**
      * 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();
-
-            Map.Entry<Integer, Integer> entry = iter.hasNext() ? iter.next() : null;
-
-            if (entry != null) {
-                id0 = entry.getKey();
-
-                assert entry.getValue() == 0;
-            }
-            else
-                id0 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id1 = entry.getKey();
-
-                assert entry.getValue() == 1;
-            }
-            else
-                id1 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id2 = entry.getKey();
-
-                assert entry.getValue() == 2;
-            }
-            else
-                id2 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id3 = entry.getKey();
-
-                assert entry.getValue() == 3;
-            }
-            else
-                id3 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id4 = entry.getKey();
-
-                assert entry.getValue() == 4;
-            }
-            else
-                id4 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id5 = entry.getKey();
-
-                assert entry.getValue() == 5;
-            }
-            else
-                id5 = 0;
-
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id6 = entry.getKey();
+    private PortableSchema(int schemaId, List<Integer> fieldIds) {
+        this.schemaId = schemaId;
 
-                assert entry.getValue() == 6;
-            }
-            else
-                id6 = 0;
+        if (fieldIds.size() <= 8) {
+            inline = true;
 
-            if ((entry = iter.hasNext() ? iter.next() : null) != null) {
-                id7 = entry.getKey();
+            Iterator<Integer> iter = fieldIds.iterator();
 
-                assert entry.getValue() == 7;
-            }
-            else
-                id7 = 0;
+            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;
 
             map = null;
         }
@@ -146,11 +99,21 @@ public class PortableSchema {
 
             id0 = id1 = id2 = id3 = id4 = id5 = id6 = id7 = 0;
 
-            map = new HashMap<>(vals);
+            map = new HashMap<>();
+
+            for (int i = 0; i < fieldIds.size(); i++)
+                map.put(fieldIds.get(i), i);
         }
     }
 
     /**
+     * @return Schema ID.
+     */
+    public int schemaId() {
+        return schemaId;
+    }
+
+    /**
      * Get field position in footer by schema ID.
      *
      * @param id Field ID.
@@ -190,4 +153,51 @@ public class PortableSchema {
             return order != null ? order : ORDER_NOT_FOUND;
         }
     }
+
+    /**
+     * 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);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
index 591857c..cb445c5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/PortableUtils.java
@@ -109,8 +109,8 @@ public class PortableUtils {
     /** Flag: offsets take 2 bytes. */
     public static final short FLAG_OFFSET_TWO_BYTES = 0x0008;
 
-    /** Flag: no field IDs in object's footer. */
-    public static final short FLAG_NO_FIELD_IDS = 0x0010;
+    /** Flag: compact footer, no field IDs. */
+    public static final short FLAG_COMPACT_FOOTER = 0x0010;
 
     /** Offset which fits into 1 byte. */
     public static final int OFFSET_1 = 1;
@@ -127,7 +127,93 @@ public class PortableUtils {
     /** Field type names. */
     private static final String[] FIELD_TYPE_NAMES;
 
+    /** FNV1 hash offset basis. */
+    private static final int FNV1_OFFSET_BASIS = 0x811C9DC5;
+
+    /** FNV1 hash prime. */
+    private static final int FNV1_PRIME = 0x01000193;
+
+    /**
+     * Static class initializer.
+     */
     static {
+        PLAIN_CLASS_TO_FLAG.put(Byte.class, GridPortableMarshaller.BYTE);
+        PLAIN_CLASS_TO_FLAG.put(Short.class, GridPortableMarshaller.SHORT);
+        PLAIN_CLASS_TO_FLAG.put(Integer.class, GridPortableMarshaller.INT);
+        PLAIN_CLASS_TO_FLAG.put(Long.class, GridPortableMarshaller.LONG);
+        PLAIN_CLASS_TO_FLAG.put(Float.class, GridPortableMarshaller.FLOAT);
+        PLAIN_CLASS_TO_FLAG.put(Double.class, GridPortableMarshaller.DOUBLE);
+        PLAIN_CLASS_TO_FLAG.put(Character.class, GridPortableMarshaller.CHAR);
+        PLAIN_CLASS_TO_FLAG.put(Boolean.class, GridPortableMarshaller.BOOLEAN);
+        PLAIN_CLASS_TO_FLAG.put(BigDecimal.class, GridPortableMarshaller.DECIMAL);
+        PLAIN_CLASS_TO_FLAG.put(String.class, GridPortableMarshaller.STRING);
+        PLAIN_CLASS_TO_FLAG.put(UUID.class, GridPortableMarshaller.UUID);
+        PLAIN_CLASS_TO_FLAG.put(Date.class, GridPortableMarshaller.DATE);
+        PLAIN_CLASS_TO_FLAG.put(Timestamp.class, GridPortableMarshaller.TIMESTAMP);
+
+        PLAIN_CLASS_TO_FLAG.put(byte[].class, GridPortableMarshaller.BYTE_ARR);
+        PLAIN_CLASS_TO_FLAG.put(short[].class, GridPortableMarshaller.SHORT_ARR);
+        PLAIN_CLASS_TO_FLAG.put(int[].class, GridPortableMarshaller.INT_ARR);
+        PLAIN_CLASS_TO_FLAG.put(long[].class, GridPortableMarshaller.LONG_ARR);
+        PLAIN_CLASS_TO_FLAG.put(float[].class, GridPortableMarshaller.FLOAT_ARR);
+        PLAIN_CLASS_TO_FLAG.put(double[].class, GridPortableMarshaller.DOUBLE_ARR);
+        PLAIN_CLASS_TO_FLAG.put(char[].class, GridPortableMarshaller.CHAR_ARR);
+        PLAIN_CLASS_TO_FLAG.put(boolean[].class, GridPortableMarshaller.BOOLEAN_ARR);
+        PLAIN_CLASS_TO_FLAG.put(BigDecimal[].class, GridPortableMarshaller.DECIMAL_ARR);
+        PLAIN_CLASS_TO_FLAG.put(String[].class, GridPortableMarshaller.STRING_ARR);
+        PLAIN_CLASS_TO_FLAG.put(UUID[].class, GridPortableMarshaller.UUID_ARR);
+        PLAIN_CLASS_TO_FLAG.put(Date[].class, GridPortableMarshaller.DATE_ARR);
+        PLAIN_CLASS_TO_FLAG.put(Timestamp[].class, GridPortableMarshaller.TIMESTAMP_ARR);
+
+        for (Map.Entry<Class<?>, Byte> entry : PLAIN_CLASS_TO_FLAG.entrySet())
+            FLAG_TO_CLASS.put(entry.getValue(), entry.getKey());
+
+        PLAIN_CLASS_TO_FLAG.put(byte.class, GridPortableMarshaller.BYTE);
+        PLAIN_CLASS_TO_FLAG.put(short.class, GridPortableMarshaller.SHORT);
+        PLAIN_CLASS_TO_FLAG.put(int.class, GridPortableMarshaller.INT);
+        PLAIN_CLASS_TO_FLAG.put(long.class, GridPortableMarshaller.LONG);
+        PLAIN_CLASS_TO_FLAG.put(float.class, GridPortableMarshaller.FLOAT);
+        PLAIN_CLASS_TO_FLAG.put(double.class, GridPortableMarshaller.DOUBLE);
+        PLAIN_CLASS_TO_FLAG.put(char.class, GridPortableMarshaller.CHAR);
+        PLAIN_CLASS_TO_FLAG.put(boolean.class, GridPortableMarshaller.BOOLEAN);
+
+        for (byte b : new byte[] {
+            BYTE, SHORT, INT, LONG, FLOAT, DOUBLE,
+            CHAR, BOOLEAN, DECIMAL, STRING, UUID, DATE, TIMESTAMP,
+            BYTE_ARR, SHORT_ARR, INT_ARR, LONG_ARR, FLOAT_ARR, DOUBLE_ARR,
+            CHAR_ARR, BOOLEAN_ARR, DECIMAL_ARR, STRING_ARR, UUID_ARR, DATE_ARR, TIMESTAMP_ARR,
+            ENUM, ENUM_ARR, NULL}) {
+
+            PLAIN_TYPE_FLAG[b] = true;
+        }
+
+        PORTABLE_CLS.add(Byte.class);
+        PORTABLE_CLS.add(Short.class);
+        PORTABLE_CLS.add(Integer.class);
+        PORTABLE_CLS.add(Long.class);
+        PORTABLE_CLS.add(Float.class);
+        PORTABLE_CLS.add(Double.class);
+        PORTABLE_CLS.add(Character.class);
+        PORTABLE_CLS.add(Boolean.class);
+        PORTABLE_CLS.add(String.class);
+        PORTABLE_CLS.add(UUID.class);
+        PORTABLE_CLS.add(Date.class);
+        PORTABLE_CLS.add(Timestamp.class);
+        PORTABLE_CLS.add(BigDecimal.class);
+        PORTABLE_CLS.add(byte[].class);
+        PORTABLE_CLS.add(short[].class);
+        PORTABLE_CLS.add(int[].class);
+        PORTABLE_CLS.add(long[].class);
+        PORTABLE_CLS.add(float[].class);
+        PORTABLE_CLS.add(double[].class);
+        PORTABLE_CLS.add(char[].class);
+        PORTABLE_CLS.add(boolean[].class);
+        PORTABLE_CLS.add(String[].class);
+        PORTABLE_CLS.add(UUID[].class);
+        PORTABLE_CLS.add(Date[].class);
+        PORTABLE_CLS.add(Timestamp[].class);
+        PORTABLE_CLS.add(BigDecimal[].class);
+
         FIELD_TYPE_NAMES = new String[104];
 
         FIELD_TYPE_NAMES[BYTE] = "byte";
@@ -168,6 +254,35 @@ public class PortableUtils {
     }
 
     /**
+     * Schema initial ID.
+     *
+     * @return ID.
+     */
+    public static int schemaInitialId() {
+        return FNV1_OFFSET_BASIS;
+    }
+
+    /**
+     * Update schema ID when new field is added.
+     *
+     * @param schemaId Current schema ID.
+     * @param fieldId Field ID.
+     * @return New schema ID.
+     */
+    public static int updateSchemaId(int schemaId, int fieldId) {
+        schemaId = schemaId ^ (fieldId & 0xFF);
+        schemaId = schemaId * FNV1_PRIME;
+        schemaId = schemaId ^ ((fieldId >> 8) & 0xFF);
+        schemaId = schemaId * FNV1_PRIME;
+        schemaId = schemaId ^ ((fieldId >> 16) & 0xFF);
+        schemaId = schemaId * FNV1_PRIME;
+        schemaId = schemaId ^ ((fieldId >> 24) & 0xFF);
+        schemaId = schemaId * FNV1_PRIME;
+
+        return schemaId;
+    }
+
+    /**
      * @param typeName Field type name.
      * @return Field type ID;
      */
@@ -198,19 +313,6 @@ public class PortableUtils {
     }
 
     /**
-     * @param typeIds Field type IDs.
-     * @return Field type names.
-     */
-    public static Map<String, String> fieldTypeNames(Map<String, Integer> typeIds) {
-        Map<String, String> names = U.newHashMap(typeIds.size());
-
-        for (Map.Entry<String, Integer> e : typeIds.entrySet())
-            names.put(e.getKey(), fieldTypeName(e.getValue()));
-
-        return names;
-    }
-
-    /**
      * Check if user type flag is set.
      *
      * @param flags Flags.
@@ -236,8 +338,8 @@ public class PortableUtils {
      * @param flags Flags.
      * @return {@code True} if set.
      */
-    public static boolean isNoFieldIds(short flags) {
-        return isFlagSet(flags, FLAG_NO_FIELD_IDS);
+    public static boolean isCompactFooter(short flags) {
+        return isFlagSet(flags, FLAG_COMPACT_FOOTER);
     }
 
     /**
@@ -251,94 +353,6 @@ public class PortableUtils {
         return (flags & flag) == flag;
     }
 
-
-    /**
-     *
-     */
-    static {
-        PORTABLE_CLS.add(Byte.class);
-        PORTABLE_CLS.add(Short.class);
-        PORTABLE_CLS.add(Integer.class);
-        PORTABLE_CLS.add(Long.class);
-        PORTABLE_CLS.add(Float.class);
-        PORTABLE_CLS.add(Double.class);
-        PORTABLE_CLS.add(Character.class);
-        PORTABLE_CLS.add(Boolean.class);
-        PORTABLE_CLS.add(String.class);
-        PORTABLE_CLS.add(UUID.class);
-        PORTABLE_CLS.add(Date.class);
-        PORTABLE_CLS.add(Timestamp.class);
-        PORTABLE_CLS.add(BigDecimal.class);
-        PORTABLE_CLS.add(byte[].class);
-        PORTABLE_CLS.add(short[].class);
-        PORTABLE_CLS.add(int[].class);
-        PORTABLE_CLS.add(long[].class);
-        PORTABLE_CLS.add(float[].class);
-        PORTABLE_CLS.add(double[].class);
-        PORTABLE_CLS.add(char[].class);
-        PORTABLE_CLS.add(boolean[].class);
-        PORTABLE_CLS.add(String[].class);
-        PORTABLE_CLS.add(UUID[].class);
-        PORTABLE_CLS.add(Date[].class);
-        PORTABLE_CLS.add(Timestamp[].class);
-        PORTABLE_CLS.add(BigDecimal[].class);
-    }
-
-    /**
-     *
-     */
-    static {
-        PLAIN_CLASS_TO_FLAG.put(Byte.class, GridPortableMarshaller.BYTE);
-        PLAIN_CLASS_TO_FLAG.put(Short.class, GridPortableMarshaller.SHORT);
-        PLAIN_CLASS_TO_FLAG.put(Integer.class, GridPortableMarshaller.INT);
-        PLAIN_CLASS_TO_FLAG.put(Long.class, GridPortableMarshaller.LONG);
-        PLAIN_CLASS_TO_FLAG.put(Float.class, GridPortableMarshaller.FLOAT);
-        PLAIN_CLASS_TO_FLAG.put(Double.class, GridPortableMarshaller.DOUBLE);
-        PLAIN_CLASS_TO_FLAG.put(Character.class, GridPortableMarshaller.CHAR);
-        PLAIN_CLASS_TO_FLAG.put(Boolean.class, GridPortableMarshaller.BOOLEAN);
-        PLAIN_CLASS_TO_FLAG.put(BigDecimal.class, GridPortableMarshaller.DECIMAL);
-        PLAIN_CLASS_TO_FLAG.put(String.class, GridPortableMarshaller.STRING);
-        PLAIN_CLASS_TO_FLAG.put(UUID.class, GridPortableMarshaller.UUID);
-        PLAIN_CLASS_TO_FLAG.put(Date.class, GridPortableMarshaller.DATE);
-        PLAIN_CLASS_TO_FLAG.put(Timestamp.class, GridPortableMarshaller.TIMESTAMP);
-
-        PLAIN_CLASS_TO_FLAG.put(byte[].class, GridPortableMarshaller.BYTE_ARR);
-        PLAIN_CLASS_TO_FLAG.put(short[].class, GridPortableMarshaller.SHORT_ARR);
-        PLAIN_CLASS_TO_FLAG.put(int[].class, GridPortableMarshaller.INT_ARR);
-        PLAIN_CLASS_TO_FLAG.put(long[].class, GridPortableMarshaller.LONG_ARR);
-        PLAIN_CLASS_TO_FLAG.put(float[].class, GridPortableMarshaller.FLOAT_ARR);
-        PLAIN_CLASS_TO_FLAG.put(double[].class, GridPortableMarshaller.DOUBLE_ARR);
-        PLAIN_CLASS_TO_FLAG.put(char[].class, GridPortableMarshaller.CHAR_ARR);
-        PLAIN_CLASS_TO_FLAG.put(boolean[].class, GridPortableMarshaller.BOOLEAN_ARR);
-        PLAIN_CLASS_TO_FLAG.put(BigDecimal[].class, GridPortableMarshaller.DECIMAL_ARR);
-        PLAIN_CLASS_TO_FLAG.put(String[].class, GridPortableMarshaller.STRING_ARR);
-        PLAIN_CLASS_TO_FLAG.put(UUID[].class, GridPortableMarshaller.UUID_ARR);
-        PLAIN_CLASS_TO_FLAG.put(Date[].class, GridPortableMarshaller.DATE_ARR);
-        PLAIN_CLASS_TO_FLAG.put(Timestamp[].class, GridPortableMarshaller.TIMESTAMP_ARR);
-
-        for (Map.Entry<Class<?>, Byte> entry : PLAIN_CLASS_TO_FLAG.entrySet())
-            FLAG_TO_CLASS.put(entry.getValue(), entry.getKey());
-
-        PLAIN_CLASS_TO_FLAG.put(byte.class, GridPortableMarshaller.BYTE);
-        PLAIN_CLASS_TO_FLAG.put(short.class, GridPortableMarshaller.SHORT);
-        PLAIN_CLASS_TO_FLAG.put(int.class, GridPortableMarshaller.INT);
-        PLAIN_CLASS_TO_FLAG.put(long.class, GridPortableMarshaller.LONG);
-        PLAIN_CLASS_TO_FLAG.put(float.class, GridPortableMarshaller.FLOAT);
-        PLAIN_CLASS_TO_FLAG.put(double.class, GridPortableMarshaller.DOUBLE);
-        PLAIN_CLASS_TO_FLAG.put(char.class, GridPortableMarshaller.CHAR);
-        PLAIN_CLASS_TO_FLAG.put(boolean.class, GridPortableMarshaller.BOOLEAN);
-
-        for (byte b : new byte[] {
-            BYTE, SHORT, INT, LONG, FLOAT, DOUBLE,
-            CHAR, BOOLEAN, DECIMAL, STRING, UUID, DATE, TIMESTAMP,
-            BYTE_ARR, SHORT_ARR, INT_ARR, LONG_ARR, FLOAT_ARR, DOUBLE_ARR,
-            CHAR_ARR, BOOLEAN_ARR, DECIMAL_ARR, STRING_ARR, UUID_ARR, DATE_ARR, TIMESTAMP_ARR,
-            ENUM, ENUM_ARR, NULL}) {
-
-            PLAIN_TYPE_FLAG[b] = true;
-        }
-    }
-
     /**
      * Write value with flag. e.g. writePlainObject(writer, (byte)77) will write two byte: {BYTE, 77}.
      *
@@ -770,7 +784,7 @@ public class PortableUtils {
      * @return Field ID length.
      */
     public static int fieldIdLength(short flags) {
-        return isNoFieldIds(flags) ? 0 : FIELD_ID_LEN;
+        return isCompactFooter(flags) ? 0 : FIELD_ID_LEN;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
index 2cc597f..d485e90 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
@@ -348,7 +348,7 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
                         typeName = metadata.typeName();
                     }
 
-                    ctx.updateMetaData(typeId, typeName, newFldsMetadata);
+                    ctx.updateMetadata(typeId, typeName, newFldsMetadata);
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
index 5e794d9..f481963 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
@@ -175,7 +175,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
                                 if (checkMeta(typeId, oldMeta, newMeta0, fields)) {
                                     newMeta0 = new BinaryMetadata(typeId, newMeta0.typeName(), fields,
-                                        newMeta0.affinityKeyFieldName());
+                                        newMeta0.affinityKeyFieldName(), newMeta0.schemas());
 
                                     metaBuf.put(typeId, newMeta0);
                                 }
@@ -450,7 +450,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     /** {@inheritDoc} */
     @Override public void updateMetaData(int typeId, String typeName, @Nullable String affKeyFieldName,
         Map<String, Integer> fieldTypeIds) throws BinaryObjectException {
-        portableCtx.updateMetaData(typeId, new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName));
+        portableCtx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, fieldTypeIds, affKeyFieldName, null));
     }
 
     /** {@inheritDoc} */
@@ -838,7 +838,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
                 if (checkMeta(typeId, oldMeta, newMeta, fields)) {
                     BinaryMetadata res = new BinaryMetadata(typeId, newMeta.typeName(), fields,
-                        newMeta.affinityKeyFieldName());
+                        newMeta.affinityKeyFieldName(), newMeta.schemas());
 
                     entry.setValue(res);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9e792606/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
index d26c4dc..1704c8a 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
@@ -97,7 +97,7 @@ public class PortableMarshaller extends AbstractMarshaller {
     private boolean keepDeserialized = DFLT_KEEP_DESERIALIZED;
 
     /** Compact footer. */
-    private boolean compactFooter =  DFLT_COMPACT_FOOTER;
+    private boolean compactFooter = DFLT_COMPACT_FOOTER;
 
     /** */
     private GridPortableMarshaller impl;


[2/3] ignite git commit: IGNITE-1816: Reworked metadata updates.

Posted by vo...@apache.org.
IGNITE-1816: Reworked metadata updates.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/b00502a6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/b00502a6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/b00502a6

Branch: refs/heads/ignite-1816
Commit: b00502a69b109ab702b3e2c90ec55e4612308935
Parents: 9e79260
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Nov 11 15:33:59 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Nov 11 15:33:59 2015 +0300

----------------------------------------------------------------------
 .../internal/portable/BinaryMetadata.java       |   4 +-
 .../internal/portable/PortableSchema.java       |  10 ++
 .../CacheObjectBinaryProcessorImpl.java         | 169 ++++++++-----------
 .../marshaller/portable/PortableMarshaller.java |   3 +-
 4 files changed, 88 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b00502a6/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 e7eb70f..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
@@ -127,8 +127,8 @@ public class BinaryMetadata implements Externalizable {
     /**
      * @return Schemas.
      */
-    @Nullable public Collection<PortableSchema> schemas() {
-        return schemas;
+    public Collection<PortableSchema> schemas() {
+        return schemas != null ? schemas : Collections.<PortableSchema>emptyList();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/b00502a6/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 a670b78..f6838c0 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
@@ -154,6 +154,16 @@ public class PortableSchema implements Serializable {
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return schemaId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        return o != null && o instanceof PortableSchema && schemaId == ((PortableSchema)o).schemaId;
+    }
+
     /**
      * Schema builder.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b00502a6/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
index f481963..01ec71c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/portable/CacheObjectBinaryProcessorImpl.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.portable.BinaryTypeImpl;
 import org.apache.ignite.internal.portable.GridPortableMarshaller;
 import org.apache.ignite.internal.portable.PortableContext;
 import org.apache.ignite.internal.portable.BinaryMetadataHandler;
+import org.apache.ignite.internal.portable.PortableSchema;
 import org.apache.ignite.internal.portable.PortableUtils;
 import org.apache.ignite.internal.portable.builder.BinaryObjectBuilderImpl;
 import org.apache.ignite.internal.portable.streams.PortableInputStream;
@@ -89,6 +90,7 @@ import java.io.ObjectOutput;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -168,17 +170,14 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
                     if (metaDataCache == null) {
                         BinaryMetadata oldMeta = metaBuf.get(typeId);
+                        BinaryMetadata mergedMeta = mergeMetadata(oldMeta, newMeta0);
 
-                        if (oldMeta == null || checkMeta(typeId, oldMeta, newMeta0, null)) {
+                        if (oldMeta != mergedMeta) {
                             synchronized (this) {
-                                Map<String, Integer> fields = new HashMap<>();
+                                mergedMeta = mergeMetadata(oldMeta, newMeta0);
 
-                                if (checkMeta(typeId, oldMeta, newMeta0, fields)) {
-                                    newMeta0 = new BinaryMetadata(typeId, newMeta0.typeName(), fields,
-                                        newMeta0.affinityKeyFieldName(), newMeta0.schemas());
-
-                                    metaBuf.put(typeId, newMeta0);
-                                }
+                                if (oldMeta != mergedMeta)
+                                    metaBuf.put(typeId, mergedMeta);
                                 else
                                     return;
                             }
@@ -188,8 +187,6 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
                             else
                                 metaBuf.remove(typeId);
                         }
-                        else
-                            return;
                     }
 
                     CacheObjectBinaryProcessorImpl.this.addMeta(typeId, newMeta0.wrap(portableCtx));
@@ -297,24 +294,22 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     private void addClientCacheMetaData(PortableMetaDataKey key, final BinaryMetadata newMeta) {
         int key0 = key.typeId();
 
-        clientMetaDataCache.compute(key0,
-            new ConcurrentHashMap8.BiFun<Integer, BinaryTypeImpl, BinaryTypeImpl>() {
-                @Override public BinaryTypeImpl apply(Integer key, BinaryTypeImpl oldMeta) {
-                    BinaryMetadata res;
-
-                    BinaryMetadata oldMeta0 = oldMeta != null ? oldMeta.metadata() : null;
+        clientMetaDataCache.compute(key0, new ConcurrentHashMap8.BiFun<Integer, BinaryTypeImpl, BinaryTypeImpl>() {
+            @Override public BinaryTypeImpl apply(Integer key, BinaryTypeImpl oldMeta) {
+                BinaryMetadata res;
 
-                    try {
-                        res = checkMeta(key, oldMeta0, newMeta, null) ? newMeta : oldMeta0;
-                    }
-                    catch (BinaryObjectException e) {
-                        res = oldMeta0;
-                    }
+                BinaryMetadata oldMeta0 = oldMeta != null ? oldMeta.metadata() : null;
 
-                    return res != null ? res.wrap(portableCtx) : null;
+                try {
+                    res = mergeMetadata(oldMeta0, newMeta);
+                }
+                catch (BinaryObjectException e) {
+                    res = oldMeta0;
                 }
+
+                return res != null ? res.wrap(portableCtx) : null;
             }
-        );
+        });
     }
 
     /** {@inheritDoc} */
@@ -464,13 +459,12 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
         try {
             BinaryMetadata oldMeta = metaDataCache.localPeek(key);
+            BinaryMetadata mergedMeta = mergeMetadata(oldMeta, newMeta0);
 
-            if (oldMeta == null || checkMeta(typeId, oldMeta, newMeta0, null)) {
-                BinaryObjectException err = metaDataCache.invoke(key, new MetaDataProcessor(typeId, newMeta0));
+            BinaryObjectException err = metaDataCache.invoke(key, new MetadataProcessor(mergedMeta));
 
-                if (err != null)
-                    throw err;
-            }
+            if (err != null)
+                throw err;
         }
         catch (CacheException e) {
             throw new BinaryObjectException("Failed to update meta data for type: " + newMeta.typeName(), e);
@@ -727,125 +721,112 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
     }
 
     /**
-     * @param typeId Type ID.
+     * Merge old and new metas.
+     *
      * @param oldMeta Old meta.
      * @param newMeta New meta.
-     * @param fields Fields map.
-     * @return Whether meta is changed.
-     * @throws org.apache.ignite.binary.BinaryObjectException In case of error.
+     * @return New meta if old meta was null, old meta if no changes detected, merged meta otherwise.
+     * @throws BinaryObjectException If merge failed due to metadata conflict.
      */
-    private static boolean checkMeta(int typeId, @Nullable BinaryMetadata oldMeta,
-        BinaryMetadata newMeta, @Nullable Map<String, Integer> fields) throws BinaryObjectException {
+    private static BinaryMetadata mergeMetadata(@Nullable BinaryMetadata oldMeta, BinaryMetadata newMeta) {
         assert newMeta != null;
 
-        Map<String, Integer> oldFields = oldMeta != null ? oldMeta.fieldsMap() : null;
-        Map<String, Integer> newFields = newMeta.fieldsMap();
-
-        boolean changed = false;
+        if (oldMeta == null)
+            return newMeta;
+        else {
+            assert oldMeta.typeId() == newMeta.typeId();
 
-        if (oldMeta != null) {
-            if (!oldMeta.typeName().equals(newMeta.typeName())) {
+            // Check type name.
+            if (!F.eq(oldMeta.typeName(), newMeta.typeName())) {
                 throw new BinaryObjectException(
-                    "Two portable types have duplicate type ID [" +
-                        "typeId=" + typeId +
-                        ", typeName1=" + oldMeta.typeName() +
-                        ", typeName2=" + newMeta.typeName() +
-                        ']'
+                    "Two portable types have duplicate type ID [" + "typeId=" + oldMeta.typeId() +
+                        ", typeName1=" + oldMeta.typeName() + ", typeName2=" + newMeta.typeName() + ']'
                 );
             }
 
+            // Check affinity field names.
             if (!F.eq(oldMeta.affinityKeyFieldName(), newMeta.affinityKeyFieldName())) {
                 throw new BinaryObjectException(
-                    "Portable type has different affinity key fields on different clients [" +
-                        "typeName=" + newMeta.typeName() +
+                    "Binary type has different affinity key fields [" + "typeName=" + newMeta.typeName() +
                         ", affKeyFieldName1=" + oldMeta.affinityKeyFieldName() +
-                        ", affKeyFieldName2=" + newMeta.affinityKeyFieldName() +
-                        ']'
+                        ", affKeyFieldName2=" + newMeta.affinityKeyFieldName() + ']'
                 );
             }
 
-            if (fields != null)
-                fields.putAll(oldFields);
-        }
-        else
-            changed = true;
+            // Check and merge fields.
+            boolean changed = false;
+
+            Map<String, Integer> mergedFields = new HashMap<>(oldMeta.fieldsMap());
+            Map<String, Integer> newFields = newMeta.fieldsMap();
 
-        for (Map.Entry<String, Integer> e : newFields.entrySet()) {
-            Integer oldTypeId = oldFields != null ? oldFields.get(e.getKey()) : null;
+            for (Map.Entry<String, Integer> newField : newFields.entrySet()) {
+                Integer oldFieldType = mergedFields.put(newField.getKey(), newField.getValue());
 
-            if (oldTypeId != null) {
-                if (!oldTypeId.equals(e.getValue())) {
+                if (oldFieldType == null)
+                    changed = true;
+                else if (!F.eq(oldFieldType, newField.getValue())) {
                     throw new BinaryObjectException(
-                        "Portable field has different types on different clients [" +
-                            "typeName=" + newMeta.typeName() +
-                            ", fieldName=" + e.getKey() +
-                            ", fieldTypeName1=" + PortableUtils.fieldTypeName(oldTypeId) +
-                            ", fieldTypeName2=" + PortableUtils.fieldTypeName(e.getValue()) +
-                            ']'
+                        "Binary type has different field types [" + "typeName=" + oldMeta.typeName() +
+                            ", fieldName=" + newField.getKey() +
+                            ", fieldTypeName1=" + PortableUtils.fieldTypeName(oldFieldType) +
+                            ", fieldTypeName2=" + PortableUtils.fieldTypeName(newField.getValue()) + ']'
                     );
                 }
             }
-            else {
-                if (fields != null)
-                    fields.put(e.getKey(), e.getValue());
 
-                changed = true;
+            // Check and merge schemas.
+            Collection<PortableSchema> mergedSchemas = new HashSet<>(oldMeta.schemas());
+
+            for (PortableSchema newSchema : newMeta.schemas()) {
+                if (mergedSchemas.add(newSchema))
+                    changed = true;
             }
-        }
 
-        return changed;
+            // Return either old meta if no changes detected, or new merged meta.
+            return changed ? new BinaryMetadata(oldMeta.typeId(), oldMeta.typeName(), mergedFields,
+                oldMeta.affinityKeyFieldName(), mergedSchemas) : oldMeta;
+        }
     }
 
     /**
+     * Processor responsible for metadata update.
      */
-    private static class MetaDataProcessor implements
-        EntryProcessor<PortableMetaDataKey, BinaryMetadata, BinaryObjectException>, Externalizable {
+    private static class MetadataProcessor
+        implements EntryProcessor<PortableMetaDataKey, BinaryMetadata, BinaryObjectException>, Externalizable {
         /** */
         private static final long serialVersionUID = 0L;
 
         /** */
-        private int typeId;
-
-        /** */
         private BinaryMetadata newMeta;
 
         /**
          * For {@link Externalizable}.
          */
-        public MetaDataProcessor() {
+        public MetadataProcessor() {
             // No-op.
         }
 
         /**
-         * @param typeId Type ID.
          * @param newMeta New metadata.
          */
-        private MetaDataProcessor(int typeId, BinaryMetadata newMeta) {
+        private MetadataProcessor(BinaryMetadata newMeta) {
             assert newMeta != null;
 
-            this.typeId = typeId;
             this.newMeta = newMeta;
         }
 
         /** {@inheritDoc} */
-        @Override public BinaryObjectException process(
-            MutableEntry<PortableMetaDataKey, BinaryMetadata> entry,
+        @Override public BinaryObjectException process(MutableEntry<PortableMetaDataKey, BinaryMetadata> entry,
             Object... args) {
             try {
                 BinaryMetadata oldMeta = entry.getValue();
 
-                Map<String, Integer> fields = new HashMap<>();
+                BinaryMetadata mergedMeta = mergeMetadata(oldMeta, newMeta);
 
-                if (checkMeta(typeId, oldMeta, newMeta, fields)) {
-                    BinaryMetadata res = new BinaryMetadata(typeId, newMeta.typeName(), fields,
-                        newMeta.affinityKeyFieldName(), newMeta.schemas());
+                if (mergedMeta != oldMeta)
+                    entry.setValue(mergedMeta);
 
-                    entry.setValue(res);
-
-                    return null;
-                }
-                else
-                    return null;
+                return null;
             }
             catch (BinaryObjectException e) {
                 return e;
@@ -854,19 +835,17 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
 
         /** {@inheritDoc} */
         @Override public void writeExternal(ObjectOutput out) throws IOException {
-            out.writeInt(typeId);
             out.writeObject(newMeta);
         }
 
         /** {@inheritDoc} */
         @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-            typeId = in.readInt();
             newMeta = (BinaryMetadata)in.readObject();
         }
 
         /** {@inheritDoc} */
         @Override public String toString() {
-            return S.toString(MetaDataProcessor.class, this);
+            return S.toString(MetadataProcessor.class, this);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/b00502a6/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
index 1704c8a..4e8217d 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/portable/PortableMarshaller.java
@@ -78,7 +78,8 @@ public class PortableMarshaller extends AbstractMarshaller {
     public static final boolean DFLT_KEEP_DESERIALIZED = true;
 
     /** Default value of "compact footer" flag. */
-    public static final boolean DFLT_COMPACT_FOOTER = true;
+    // TODO: Set to true.
+    public static final boolean DFLT_COMPACT_FOOTER = false;
 
     // TODO ignite-1282 Move to IgniteConfiguration.
     /** Class names. */


[3/3] ignite git commit: IGNITE-1816: Getting closer to finish.

Posted by vo...@apache.org.
IGNITE-1816: Getting closer to finish.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ed3472d4
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ed3472d4
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ed3472d4

Branch: refs/heads/ignite-1816
Commit: ed3472d4eece5fe6682ff6b97a5e6fcd805f5e2c
Parents: b00502a
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Nov 11 16:17:57 2015 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Nov 11 16:17:57 2015 +0300

----------------------------------------------------------------------
 .../portable/BinaryMetadataCollector.java       | 42 +++++++++++++++-----
 .../internal/portable/BinaryWriterExImpl.java   | 28 +++++++++++--
 .../portable/PortableClassDescriptor.java       | 20 +++++++---
 .../internal/portable/PortableContext.java      | 30 +++++++++-----
 .../builder/BinaryObjectBuilderImpl.java        |  4 +-
 5 files changed, 94 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ed3472d4/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..ab2fbce 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
@@ -23,10 +23,13 @@ import java.lang.reflect.Proxy;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
+
+import org.apache.ignite.binary.BinaryIdMapper;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryRawWriter;
 import org.apache.ignite.binary.BinaryWriter;
@@ -36,17 +39,32 @@ 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 +74,13 @@ class BinaryMetadataCollector implements BinaryWriter {
         return meta;
     }
 
+    /**
+     * @return Schemas.
+     */
+    Collection<PortableSchema> schemas() {
+        return Collections.singleton(schemaBuilder.build());
+    }
+
     /** {@inheritDoc} */
     @Override public void writeByte(String fieldName, byte val) throws BinaryObjectException {
         add(fieldName, PortableClassDescriptor.Mode.BYTE);
@@ -242,13 +267,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/ed3472d4/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 5a48833..23d9311 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
@@ -133,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;
@@ -1732,9 +1732,6 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
 
                 SCHEMA.set(schema);
             }
-
-            // Initialize offset when the first field is written.
-            schemaId = PortableUtils.schemaInitialId();
         }
 
         schemaId = PortableUtils.updateSchemaId(schemaId, fieldId);
@@ -1745,6 +1742,18 @@ public class BinaryWriterExImpl implements BinaryWriter, BinaryRawWriterEx, Obje
     }
 
     /**
+     * @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.
@@ -1829,6 +1838,17 @@ 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.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed3472d4/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 361c754..c6c8d34 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
@@ -80,6 +80,9 @@ public class PortableClassDescriptor {
     /** */
     private final String typeName;
 
+    /** Affinity key field name. */
+    private final String affKeyFieldName;
+
     /** */
     private final Constructor<?> ctor;
 
@@ -116,6 +119,7 @@ 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.
@@ -130,6 +134,7 @@ public class PortableClassDescriptor {
         boolean userType,
         int typeId,
         String typeName,
+        @Nullable String affKeyFieldName,
         @Nullable BinaryIdMapper idMapper,
         @Nullable BinarySerializer serializer,
         boolean metaDataEnabled,
@@ -139,12 +144,14 @@ 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.typeName = typeName;
+        this.affKeyFieldName = affKeyFieldName;
         this.serializer = serializer;
         this.idMapper = idMapper;
         this.keepDeserialized = keepDeserialized;
@@ -212,8 +219,6 @@ public class PortableClassDescriptor {
                 break;
 
             case OBJECT:
-                assert idMapper != null;
-
                 ctor = constructor(cls);
                 fields = new ArrayList<>();
                 fieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null;
@@ -565,14 +570,17 @@ public class PortableClassDescriptor {
 
                     if (obj.getClass() != BinaryMetadata.class
                         && ctx.isMetaDataChanged(typeId, writer.metaDataHashSum())) {
-                        BinaryMetadataCollector metaCollector = new BinaryMetadataCollector(typeName);
+                        BinaryMetadataCollector collector = new BinaryMetadataCollector(typeId, typeName, idMapper);
 
                         if (serializer != null)
-                            serializer.writeBinary(obj, metaCollector);
+                            serializer.writeBinary(obj, collector);
                         else
-                            ((Binarylizable)obj).writeBinary(metaCollector);
+                            ((Binarylizable)obj).writeBinary(collector);
+
+                        BinaryMetadata meta = new BinaryMetadata(typeId, typeName, collector.meta(), affKeyFieldName,
+                            collector.schemas());
 
-                        ctx.updateMetadata(typeId, typeName, metaCollector.meta());
+                        ctx.updateMetadata(typeId, meta);
                     }
                 }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed3472d4/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 939faa0..89c8339 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
@@ -130,6 +130,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);
 
@@ -509,6 +512,7 @@ public class PortableContext implements Externalizable {
                 false,
                 clsName.hashCode(),
                 clsName,
+                null,
                 BASIC_CLS_ID_MAPPER,
                 null,
                 false,
@@ -555,6 +559,7 @@ public class PortableContext implements Externalizable {
             true,
             typeId,
             typeName,
+            null,
             idMapper,
             null,
             true,
@@ -700,6 +705,7 @@ public class PortableContext implements Externalizable {
             false,
             id,
             typeName,
+            null,
             DFLT_ID_MAPPER,
             null,
             false,
@@ -751,6 +757,11 @@ 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);
@@ -765,6 +776,7 @@ public class PortableContext implements Externalizable {
                 true,
                 id,
                 typeName,
+                affKeyFieldName,
                 idMapper,
                 serializer,
                 true,
@@ -811,6 +823,14 @@ public class PortableContext implements Externalizable {
 
     /**
      * @param typeId Type ID.
+     * @return Affinity key field name.
+     */
+    public String affinityKeyFieldName(int typeId) {
+        return affKeyFieldNames.get(typeId);
+    }
+
+    /**
+     * @param typeId Type ID.
      * @param metaHashSum Meta data hash sum.
      * @return Whether meta is changed.
      */
@@ -832,16 +852,6 @@ public class PortableContext implements Externalizable {
 
     /**
      * @param typeId Type ID.
-     * @param typeName Type name.
-     * @param fields Fields map.
-     * @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, null));
-    }
-
-    /**
-     * @param typeId Type ID.
      * @param meta Meta data.
      * @throws BinaryObjectException In case of error.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ed3472d4/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
index d485e90..402363b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/portable/builder/BinaryObjectBuilderImpl.java
@@ -22,6 +22,7 @@ import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.binary.BinaryObjectBuilder;
 import org.apache.ignite.binary.BinaryObjectException;
 import org.apache.ignite.binary.BinaryType;
+import org.apache.ignite.internal.portable.BinaryMetadata;
 import org.apache.ignite.internal.portable.BinaryObjectImpl;
 import org.apache.ignite.internal.portable.BinaryObjectOffheapImpl;
 import org.apache.ignite.internal.portable.BinaryWriterExImpl;
@@ -348,7 +349,8 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder {
                         typeName = metadata.typeName();
                     }
 
-                    ctx.updateMetadata(typeId, typeName, newFldsMetadata);
+                    ctx.updateMetadata(typeId, new BinaryMetadata(typeId, typeName, newFldsMetadata,
+                        ctx.affinityKeyFieldName(typeId), Collections.singleton(writer.currentSchema())));
                 }
             }