IGNITE-3191: Fields are now sorted for binary objects which don't implement Binarylizable interface. This closes #1197.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/6e36a795 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/6e36a795 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/6e36a795 Branch: refs/heads/ignite-4242 Commit: 6e36a7950db84913ddfd0d98f5a0b50923d2a29c Parents: a2a3bed Author: tledkov-gridgain <[email protected]> Authored: Tue Nov 15 12:42:29 2016 +0300 Committer: devozerov <[email protected]> Committed: Tue Nov 15 12:42:29 2016 +0300 ---------------------------------------------------------------------- .../apache/ignite/IgniteSystemProperties.java | 9 +++++ .../internal/binary/BinaryClassDescriptor.java | 37 ++++++++++++++++---- .../ignite/internal/binary/BinaryContext.java | 11 ++---- .../ignite/internal/binary/BinaryUtils.java | 4 +++ .../binary/builder/BinaryObjectBuilderImpl.java | 6 +++- 5 files changed, 51 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/6e36a795/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java index a75027b..22cb9a6 100644 --- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java +++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java @@ -478,6 +478,15 @@ public final class IgniteSystemProperties { public static final String IGNITE_BINARY_DONT_WRAP_TREE_STRUCTURES = "IGNITE_BINARY_DONT_WRAP_TREE_STRUCTURES"; /** + * When set to {@code true} fields are written by BinaryMarshaller in sorted order. Otherwise + * the natural order is used. + * <p> + * @deprecated Should be removed in Apache Ignite 2.0. + */ + @Deprecated + public static final String IGNITE_BINARY_SORT_OBJECT_FIELDS = "IGNITE_BINARY_SORT_OBJECT_FIELDS"; + + /** * Enforces singleton. */ private IgniteSystemProperties() { http://git-wip-us.apache.org/repos/asf/ignite/blob/6e36a795/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java index 4c824d4..d05ce71 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryClassDescriptor.java @@ -25,14 +25,15 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; 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; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.UUID; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.binary.BinaryObjectException; @@ -120,6 +121,9 @@ public class BinaryClassDescriptor { /** */ private final Class<?>[] intfs; + /** Whether stable schema was published. */ + private volatile boolean stableSchemaPublished; + /** * @param ctx Context. * @param cls Class. @@ -269,10 +273,14 @@ public class BinaryClassDescriptor { case OBJECT: // Must not use constructor to honor transient fields semantics. ctor = null; - ArrayList<BinaryFieldAccessor> fields0 = new ArrayList<>(); stableFieldsMeta = metaDataEnabled ? new HashMap<String, Integer>() : null; - BinarySchema.Builder schemaBuilder = BinarySchema.Builder.newBuilder(); + Map<Object, BinaryFieldAccessor> fields0; + + if (BinaryUtils.FIELDS_SORTED_ORDER) + fields0 = new TreeMap<>(); + else + fields0 = new LinkedHashMap<>(); Set<String> duplicates = duplicateFields(cls); @@ -300,9 +308,7 @@ public class BinaryClassDescriptor { BinaryFieldAccessor fieldInfo = BinaryFieldAccessor.create(f, fieldId); - fields0.add(fieldInfo); - - schemaBuilder.addField(fieldId); + fields0.put(name, fieldInfo); if (metaDataEnabled) stableFieldsMeta.put(name, fieldInfo.mode().typeId()); @@ -310,7 +316,12 @@ public class BinaryClassDescriptor { } } - fields = fields0.toArray(new BinaryFieldAccessor[fields0.size()]); + fields = fields0.values().toArray(new BinaryFieldAccessor[fields0.size()]); + + BinarySchema.Builder schemaBuilder = BinarySchema.Builder.newBuilder(); + + for (BinaryFieldAccessor field : fields) + schemaBuilder.addField(field.id); stableSchema = schemaBuilder.build(); @@ -747,6 +758,18 @@ public class BinaryClassDescriptor { break; case OBJECT: + if (userType && !stableSchemaPublished) { + // Update meta before write object with new schema + BinaryMetadata meta = new BinaryMetadata(typeId, typeName, stableFieldsMeta, + affKeyFieldName, Collections.singleton(stableSchema), false); + + ctx.updateMetadata(typeId, meta); + + schemaReg.addSchema(stableSchema.schemaId(), stableSchema); + + stableSchemaPublished = true; + } + if (preWrite(writer, obj)) { try { for (BinaryFieldAccessor info : fields) http://git-wip-us.apache.org/repos/asf/ignite/blob/6e36a795/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java index 2ac8b7f..a72e7ac 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java @@ -785,12 +785,9 @@ public class BinaryContext { registered ); - if (!deserialize) { - Collection<BinarySchema> schemas = desc.schema() != null ? Collections.singleton(desc.schema()) : null; - + if (!deserialize) metaHnd.addMeta(typeId, - new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, schemas, desc.isEnum()).wrap(this)); - } + new BinaryMetadata(typeId, typeName, desc.fieldsMeta(), affFieldName, null, desc.isEnum()).wrap(this)); descByCls.put(cls, desc); @@ -1123,7 +1120,6 @@ public class BinaryContext { cls2Mappers.put(clsName, mapper); Map<String, Integer> fieldsMeta = null; - Collection<BinarySchema> schemas = null; if (cls != null) { if (serializer == null) { @@ -1148,7 +1144,6 @@ public class BinaryContext { ); fieldsMeta = desc.fieldsMeta(); - schemas = desc.schema() != null ? Collections.singleton(desc.schema()) : null; descByCls.put(cls, desc); @@ -1157,7 +1152,7 @@ public class BinaryContext { predefinedTypes.put(id, desc); } - metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, schemas, isEnum).wrap(this)); + metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, null, isEnum).wrap(this)); } /** http://git-wip-us.apache.org/repos/asf/ignite/blob/6e36a795/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index 25d87ff..b304082 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -128,6 +128,10 @@ public class BinaryUtils { public static final boolean WRAP_TREES = !IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_BINARY_DONT_WRAP_TREE_STRUCTURES); + /** Whether to sort field in binary objects (doesn't affect Binarylizable). */ + public static final boolean FIELDS_SORTED_ORDER = + IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_BINARY_SORT_OBJECT_FIELDS); + /** Field type names. */ private static final String[] FIELD_TYPE_NAMES; http://git-wip-us.apache.org/repos/asf/ignite/blob/6e36a795/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java index 2c76192..f0bc874 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/builder/BinaryObjectBuilderImpl.java @@ -42,6 +42,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; +import java.util.TreeMap; /** * @@ -522,7 +523,10 @@ public class BinaryObjectBuilderImpl implements BinaryObjectBuilder { Object val = val0 == null ? new BinaryValueWithType(BinaryUtils.typeByClass(Object.class), null) : val0; if (assignedVals == null) - assignedVals = new LinkedHashMap<>(); + if (BinaryUtils.FIELDS_SORTED_ORDER) + assignedVals = new TreeMap<>(); + else + assignedVals = new LinkedHashMap<>(); Object oldVal = assignedVals.put(name, val);
