IGNITE-141 - Marshallers refactoring
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/e9d99de8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/e9d99de8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/e9d99de8 Branch: refs/heads/ignite-141 Commit: e9d99de8a042c378d24b579ab49d251f780a775c Parents: 6a8b322 Author: Valentin Kulichenko <[email protected]> Authored: Sat Feb 28 23:38:44 2015 -0800 Committer: Valentin Kulichenko <[email protected]> Committed: Sat Feb 28 23:38:44 2015 -0800 ---------------------------------------------------------------------- .../apache/ignite/internal/IgniteKernal.java | 8 +- .../optimized/OptimizedClassDescriptor.java | 49 +- .../optimized/OptimizedMarshaller.java | 26 +- .../optimized/OptimizedMarshallerIdMapper.java | 33 + .../optimized/OptimizedMarshallerUtils.java | 67 +- .../optimized/OptimizedObjectInputStream.java | 16 +- .../optimized/OptimizedObjectOutputStream.java | 18 +- .../marshaller/optimized/classnames.properties | 1470 ++++++++++++++++++ .../OptimizedObjectStreamSelfTest.java | 6 +- 9 files changed, 1597 insertions(+), 96 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/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 55bc1f8..2e517e8 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 @@ -2793,11 +2793,15 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable { /** {@inheritDoc} */ @Override public void run() { try { + // TODO: IGNITE-141 - Remove debug + U.debug(">>> REGISTER: " + clsName); + String old = cache.putIfAbsent(typeId, clsName); - // TODO: IGNITE-141 - proper message if (old != null && !old.equals(clsName)) - throw new IgniteException("Collision."); + throw new IgniteException("Type ID collision acquired in OptimizedMarshaller. Use " + + "OptimizedMarshallerIdMapper to resolve it [id=" + typeId + ", clsName1=" + clsName + + "clsName2=" + old + ']'); } catch (IgniteCheckedException e) { throw U.convertException(e); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java index 7c3c205..e50cf7b 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedClassDescriptor.java @@ -130,19 +130,22 @@ class OptimizedClassDescriptor { private static final int TYPE_SERIALIZABLE = 51; /** Class. */ - private Class<?> cls; + private final Class<?> cls; /** Context. */ - private MarshallerContext ctx; + private final MarshallerContext ctx; + + /** ID mapper. */ + private final OptimizedMarshallerIdMapper mapper; + + /** Class name. */ + private final String name; /** Type ID. */ - private int typeId; + private final int typeId; /** Short ID. */ - private short checksum; - - /** Class name. */ - private String name; + private final short checksum; /** Class type. */ private int type; @@ -157,7 +160,7 @@ class OptimizedClassDescriptor { private boolean isSerial; /** Excluded flag. */ - private final boolean excluded; + private boolean excluded; /** {@code True} if descriptor is for {@link Class}. */ private boolean isCls; @@ -203,19 +206,32 @@ class OptimizedClassDescriptor { * * @param cls Class. * @param ctx Context. + * @param mapper ID mapper. * @throws IOException In case of error. */ @SuppressWarnings("ForLoopReplaceableByForEach") - OptimizedClassDescriptor(Class<?> cls, MarshallerContext ctx) throws IOException { + OptimizedClassDescriptor(Class<?> cls, MarshallerContext ctx, OptimizedMarshallerIdMapper mapper) + throws IOException { this.cls = cls; this.ctx = ctx; + this.mapper = mapper; - // TODO: IGNITE-141 - resolve - typeId = cls.getName().hashCode(); + name = cls.getName(); - excluded = MarshallerExclusions.isExcluded(cls); + int typeId; - name = cls.getName(); + if (mapper != null) { + typeId = mapper.typeId(name); + + if (typeId == 0) + typeId = name.hashCode(); + } + else + typeId = name.hashCode(); + + this.typeId = typeId; + + excluded = MarshallerExclusions.isExcluded(cls); if (!excluded) { Class<?> parent; @@ -777,8 +793,7 @@ class OptimizedClassDescriptor { break; case TYPE_CLS: - // TODO: IGNITE-141 - Do not acquire descriptor? - OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor((Class<?>)obj, ctx); + OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor((Class<?>)obj, ctx, mapper); out.writeInt(desc.typeId()); @@ -901,8 +916,8 @@ class OptimizedClassDescriptor { return in.readDate(); case TYPE_CLS: - // TODO: IGNITE-141 - Do not acquire descriptor? - return OptimizedMarshallerUtils.classDescriptor(in.readInt(), in.classLoader(), ctx).describedClass(); + return OptimizedMarshallerUtils.classDescriptor(in.readInt(), in.classLoader(), ctx, mapper). + describedClass(); case TYPE_EXTERNALIZABLE: verifyChecksum(in.readShort()); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java index f107c08..4779eb6 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshaller.java @@ -79,6 +79,9 @@ public class OptimizedMarshaller extends AbstractMarshaller { /** Whether or not to require an object to be serializable in order to be marshalled. */ private boolean requireSer = true; + /** ID mapper. */ + private OptimizedMarshallerIdMapper mapper; + /** * Creates new marshaller will all defaults. * @@ -110,6 +113,15 @@ public class OptimizedMarshaller extends AbstractMarshaller { } /** + * Sets ID mapper. + * + * @param mapper ID mapper. + */ + public void setIdMapper(OptimizedMarshallerIdMapper mapper) { + this.mapper = mapper; + } + + /** * Specifies size of cached object streams used by marshaller. Object streams are cached for * performance reason to avoid costly recreation for every serialization routine. If {@code 0} (default), * pool is not used and each thread has its own cached object stream which it keeps reusing. @@ -137,8 +149,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { try { objOut = OptimizedObjectStreamRegistry.out(); - objOut.context(ctx); - objOut.requireSerializable(requireSer); + objOut.context(ctx, mapper, requireSer); objOut.out().outputStream(out); @@ -159,8 +170,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { try { objOut = OptimizedObjectStreamRegistry.out(); - objOut.context(ctx); - objOut.requireSerializable(requireSer); + objOut.context(ctx, mapper, requireSer); objOut.writeObject(obj); @@ -175,6 +185,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { } /** {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override public <T> T unmarshal(InputStream in, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { assert in != null; @@ -183,8 +194,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { try { objIn = OptimizedObjectStreamRegistry.in(); - objIn.context(ctx); - objIn.classLoader(clsLdr != null ? clsLdr : dfltClsLdr); + objIn.context(ctx, mapper, clsLdr != null ? clsLdr : dfltClsLdr); objIn.in().inputStream(in); @@ -204,6 +214,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { } /** {@inheritDoc} */ + @SuppressWarnings("unchecked") @Override public <T> T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { assert arr != null; @@ -212,8 +223,7 @@ public class OptimizedMarshaller extends AbstractMarshaller { try { objIn = OptimizedObjectStreamRegistry.in(); - objIn.context(ctx); - objIn.classLoader(clsLdr != null ? clsLdr : dfltClsLdr); + objIn.context(ctx, mapper, clsLdr != null ? clsLdr : dfltClsLdr); objIn.in().bytes(arr, arr.length); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java new file mode 100644 index 0000000..e4e2627 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerIdMapper.java @@ -0,0 +1,33 @@ +/* + * 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.marshaller.optimized; + +/** + * ID mapper. + */ +public interface OptimizedMarshallerIdMapper { + /** + * Gets type ID for provided class name. + * <p> + * If {@code 0} is returned, hash code of class name will be used. + * + * @param clsName Class name. + * @return Type ID. + */ + public int typeId(String clsName); +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java index 031e876..01cc348 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedMarshallerUtils.java @@ -17,13 +17,7 @@ package org.apache.ignite.marshaller.optimized; -import org.apache.ignite.internal.processors.cache.*; -import org.apache.ignite.internal.processors.cache.distributed.*; -import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.*; -import org.apache.ignite.internal.processors.cache.transactions.*; -import org.apache.ignite.internal.processors.cache.version.*; import org.apache.ignite.internal.util.*; -import org.apache.ignite.internal.util.lang.*; import org.apache.ignite.internal.util.typedef.*; import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.lang.*; @@ -57,38 +51,8 @@ class OptimizedMarshallerUtils { /** UTF-8 character name. */ static final Charset UTF_8 = Charset.forName("UTF-8"); - /** Predefined classes. */ - private static final Class[] PREDEFINED = new Class[] { - byte[].class, - Boolean.class, - Integer.class, - String.class, - UUID.class, - ArrayList.class, - LinkedList.class, - HashSet.class, - HashMap.class, - - GridDhtPartitionMap.class, - GridDhtPartitionFullMap.class, - GridCacheMvccCandidate.class, - GridCacheVersion.class, - IgniteTxEntry.class, - IgnitePredicate[].class, - IgniteExternalizableExpiryPolicy.class, - IgniteTxKey.class, - GridCacheReturn.class, - GridTuple4.class, - GridCacheEntryInfo.class, - GridLeanMap.class - }; - - /** Predefined class names. */ - private static final String[] PREDEFINED_NAMES = new String[] { - "org.apache.ignite.internal.GridTopic$T7", - "org.apache.ignite.internal.util.lang.GridFunc$37", - "org.apache.ignite.internal.util.GridLeanMap$Map3" - }; + /** Classnames file path. */ + private static final String CLS_NAMES_FILE = "org/apache/ignite/marshaller/optimized/classnames.properties"; /** Class descriptors by class. */ private static final ConcurrentMap<Class, OptimizedClassDescriptor> DESC_BY_CLS = new ConcurrentHashMap8<>(256); @@ -98,17 +62,20 @@ class OptimizedMarshallerUtils { new ConcurrentHashMap8<>(256); static { - for (Class cls : PREDEFINED) - CLS_BY_ID.put(cls.getName().hashCode(), F.t(cls, true)); - try { - for (String clsName : PREDEFINED_NAMES) { - Class cls = U.forName(clsName, OptimizedMarshallerUtils.class.getClassLoader()); + ClassLoader ldr = OptimizedMarshallerUtils.class.getClassLoader(); + + BufferedReader rdr = new BufferedReader(new InputStreamReader(ldr.getResourceAsStream(CLS_NAMES_FILE))); + + String clsName; + + while ((clsName = rdr.readLine()) != null) { + Class cls = U.forName(clsName, ldr); CLS_BY_ID.put(cls.getName().hashCode(), F.t(cls, true)); } } - catch (ClassNotFoundException e) { + catch (IOException | ClassNotFoundException e) { throw new IllegalStateException(e); } } @@ -124,14 +91,16 @@ class OptimizedMarshallerUtils { * * @param cls Class. * @param ctx Context. + * @param mapper ID mapper. * @return Descriptor. * @throws IOException In case of error. */ - static OptimizedClassDescriptor classDescriptor(Class cls, MarshallerContext ctx) throws IOException { + static OptimizedClassDescriptor classDescriptor(Class cls, MarshallerContext ctx, + OptimizedMarshallerIdMapper mapper) throws IOException { OptimizedClassDescriptor desc = DESC_BY_CLS.get(cls); if (desc == null) { - desc = new OptimizedClassDescriptor(cls, ctx); + desc = new OptimizedClassDescriptor(cls, ctx, mapper); if (CLS_BY_ID.putIfAbsent(desc.typeId(), F.t(cls, false)) == null) ctx.registerClass(desc.typeId(), cls.getName()); @@ -151,11 +120,13 @@ class OptimizedMarshallerUtils { * @param id ID. * @param ldr Class loader. * @param ctx Context. + * @param mapper ID mapper. * @return Descriptor. * @throws IOException In case of error. * @throws ClassNotFoundException If class was not found. */ - static OptimizedClassDescriptor classDescriptor(int id, ClassLoader ldr, MarshallerContext ctx) + static OptimizedClassDescriptor classDescriptor(int id, ClassLoader ldr, MarshallerContext ctx, + OptimizedMarshallerIdMapper mapper) throws IOException, ClassNotFoundException { Class cls = CLS_BY_ID.get(id).get1(); @@ -172,7 +143,7 @@ class OptimizedMarshallerUtils { cls = old.get1(); } - return classDescriptor(cls, ctx); + return classDescriptor(cls, ctx, mapper); } /** http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java index ad10638..50e5551 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectInputStream.java @@ -48,6 +48,9 @@ class OptimizedObjectInputStream extends ObjectInputStream { private MarshallerContext ctx; /** */ + private OptimizedMarshallerIdMapper mapper; + + /** */ private ClassLoader clsLdr; /** */ @@ -78,15 +81,12 @@ class OptimizedObjectInputStream extends ObjectInputStream { /** * @param ctx Context. - */ - void context(MarshallerContext ctx) { - this.ctx = ctx; - } - - /** + * @param mapper ID mapper. * @param clsLdr Class loader. */ - void classLoader(ClassLoader clsLdr) { + void context(MarshallerContext ctx, OptimizedMarshallerIdMapper mapper, ClassLoader clsLdr) { + this.ctx = ctx; + this.mapper = mapper; this.clsLdr = clsLdr; } @@ -149,7 +149,7 @@ class OptimizedObjectInputStream extends ObjectInputStream { case OBJECT: int typeId = readInt(); - OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor(typeId, clsLdr, ctx); + OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor(typeId, clsLdr, ctx, mapper); curCls = desc.describedClass(); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/e9d99de8/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java index fdcb78d..1e250d8 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/OptimizedObjectOutputStream.java @@ -50,6 +50,9 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { private MarshallerContext ctx; /** */ + private OptimizedMarshallerIdMapper mapper; + + /** */ private boolean requireSer; /** */ @@ -74,15 +77,12 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { /** * @param ctx Context. - */ - void context(MarshallerContext ctx) { - this.ctx = ctx; - } - - /** + * @param mapper ID mapper. * @param requireSer Require {@link Serializable} flag. */ - void requireSerializable(boolean requireSer) { + void context(MarshallerContext ctx, OptimizedMarshallerIdMapper mapper, boolean requireSer) { + this.ctx = ctx; + this.mapper = mapper; this.requireSer = requireSer; } @@ -152,7 +152,7 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { else { Class<?> cls = obj.getClass(); - OptimizedClassDescriptor desc = classDescriptor(cls, ctx); + OptimizedClassDescriptor desc = classDescriptor(cls, ctx, mapper); if (desc.excluded()) { writeByte(NULL); @@ -176,7 +176,7 @@ class OptimizedObjectOutputStream extends ObjectOutputStream { if (obj0 != obj) { obj = obj0; - desc = classDescriptor(obj.getClass(), ctx); + desc = classDescriptor(obj.getClass(), ctx, mapper); } if (handle >= 0) {
