Repository: incubator-ignite Updated Branches: refs/heads/ignite-950 5e9a45f0c -> 99c88b7cb
ignite-950: added CacheObject implementations for footer enabled classes, injected the implementation in IgniteCacheObjectProcessor Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/99c88b7c Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/99c88b7c Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/99c88b7c Branch: refs/heads/ignite-950 Commit: 99c88b7cbfd55698c88a25b5259714954cd50f7d Parents: 5e9a45f Author: Denis Magda <dma...@gridgain.com> Authored: Wed Jun 17 15:28:27 2015 +0300 Committer: Denis Magda <dma...@gridgain.com> Committed: Wed Jun 17 15:28:27 2015 +0300 ---------------------------------------------------------------------- .../ignite/codegen/MessageCodeGenerator.java | 3 +- .../communication/GridIoMessageFactory.java | 10 +- .../internal/processors/cache/CacheObject.java | 2 + .../processors/cache/CacheObjectImpl.java | 22 -- .../cache/CacheOptimizedObjectImpl.java | 339 +++++++++++++++++++ .../cache/KeyCacheOptimizedObjectImpl.java | 99 ++++++ .../cacheobject/IgniteCacheObjectProcessor.java | 24 +- .../IgniteCacheObjectProcessorImpl.java | 159 ++++++++- .../optimized/OptimizedObjectInputStream.java | 6 +- .../optimized/ext/OptimizedMarshallerExt.java | 57 +++- .../ext/OptimizedObjectInputStreamExt.java | 16 +- .../marshaller/optimized/ext/package-info.java | 2 +- .../ext/OptimizedMarshallerExtSelfTest.java | 10 +- 13 files changed, 672 insertions(+), 77 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java ---------------------------------------------------------------------- diff --git a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java index 0540148..4780ee4 100644 --- a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java +++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java @@ -18,6 +18,7 @@ package org.apache.ignite.codegen; import org.apache.ignite.internal.*; +import org.apache.ignite.internal.processors.cache.*; import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.lang.*; import org.apache.ignite.plugin.extensions.communication.*; @@ -142,7 +143,7 @@ public class MessageCodeGenerator { MessageCodeGenerator gen = new MessageCodeGenerator(srcDir); -// gen.generateAndWrite(DataStreamerEntry.class); + gen.generateAndWrite(CacheOptimizedObjectImpl.class); // gen.generateAndWrite(GridDistributedLockRequest.class); // gen.generateAndWrite(GridDistributedLockResponse.class); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java index 7fe8da8..4c8fec5 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java @@ -600,7 +600,15 @@ public class GridIoMessageFactory implements MessageFactory { break; - // [-3..112] - this + case 113: + msg = new CacheOptimizedObjectImpl(); + + break; + + case 114: + msg = new KeyCacheOptimizedObjectImpl(); + + // [-3..114] - this // [120..123] - DR // [-4..-22] - SQL default: http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java index 2f77e86..14c6196 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObject.java @@ -31,6 +31,8 @@ public interface CacheObject extends Message { /** */ public static final byte TYPE_BYTE_ARR = 2; + public static final byte TYPE_OPTIMIZED = 3; + /** * @param ctx Context. * @param cpy If {@code true} need to copy value. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectImpl.java index 49c0262..96603f9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectImpl.java @@ -77,7 +77,6 @@ public class CacheObjectImpl extends CacheObjectAdapter { catch (IgniteCheckedException e) { throw new IgniteException("Failed to unmarshall object.", e); } - } /** {@inheritDoc} */ @@ -104,27 +103,6 @@ public class CacheObjectImpl extends CacheObjectAdapter { val = ctx.processor().unmarshal(ctx, valBytes, ldr); } - /** - * Gets field value. - * - * @param fieldName Field name. - * @return Field value. - * @throws IgniteCheckedException In case of any other error. - */ - @Nullable public <F> F field(String fieldName) throws IgniteCheckedException { - return null; - } - - /** - * Checks whether field is set. - * - * @param fieldName Field name. - * @return {@code true} if field is set. - */ - public boolean hasField(String fieldName) { - return false; - } - /** {@inheritDoc} */ @Override public byte directType() { return 89; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOptimizedObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOptimizedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOptimizedObjectImpl.java new file mode 100644 index 0000000..734451e --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheOptimizedObjectImpl.java @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.apache.ignite.*; +import org.apache.ignite.internal.util.typedef.internal.*; +import org.apache.ignite.marshaller.optimized.ext.*; +import org.apache.ignite.plugin.extensions.communication.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.nio.*; + +/** + * Cache object implementation for classes that support footer injection is their serialized form thus enabling fields + * search and extraction without necessity to fully deserialize an object. + */ +public class CacheOptimizedObjectImpl extends CacheObjectAdapter { + /** */ + private static final long serialVersionUID = 0L; + + /** */ + protected int start; + + /** */ + protected int len; + + /** + * For {@link Externalizable}. + */ + public CacheOptimizedObjectImpl() { + // No-op + } + + /** + * Instantiates {@code CacheOptimizedObjectImpl} with object. + * @param val Object. + */ + public CacheOptimizedObjectImpl(Object val) { + this(val, null, 0, 0); + } + + /** + * Instantiates {@code CacheOptimizedObjectImpl} with object's serialized form. + * @param valBytes Object serialized to byte array. + * @param start Object's start in the array. + * @param len Object's len in the array. + */ + public CacheOptimizedObjectImpl(byte[] valBytes, int start, int len) { + this(null, valBytes, start, len); + } + + /** + * Instantiates {@code CacheOptimizedObjectImpl} with object's serialized form and value. + * @param val Object. + * @param valBytes Object serialized to byte array. + */ + public CacheOptimizedObjectImpl(Object val, byte[] valBytes) { + this(val, valBytes, 0, valBytes != null ? valBytes.length : 0); + } + + /** + * Instantiates {@code CacheOptimizedObjectImpl}. + * @param val Object. + * @param valBytes Object in a serialized form. + * @param start Object's start in the array. + * @param len Object's len in the array. + */ + public CacheOptimizedObjectImpl(Object val, byte[] valBytes, int start, int len) { + assert val != null || (valBytes != null && start >= 0 && len > 0); + + this.val = val; + this.valBytes = valBytes; + this.start = start; + this.len = len; + } + + /** {@inheritDoc} */ + @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) { + cpy = cpy && needCopy(ctx); + + try { + if (cpy) { + toMarshaledFormIfNeeded(ctx); + + return (T)ctx.processor().unmarshal(ctx, valBytes, + val == null ? ctx.kernalContext().config().getClassLoader() : val.getClass().getClassLoader()); + } + + if (val != null) + return (T)val; + + assert valBytes != null; + + Object val = ctx.processor().unmarshal(ctx, valBytes, start, len, + ctx.kernalContext().config().getClassLoader()); + + if (ctx.storeValue()) + this.val = val; + + return (T)val; + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to unmarshall object.", e); + } + } + + /** {@inheritDoc} */ + @Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException { + toMarshaledFormIfNeeded(ctx); + + if (detached()) + return valBytes; + + byte[] arr = new byte[len]; + + U.arrayCopy(valBytes, start, arr, 0, len); + + return arr; + } + + /** {@inheritDoc} */ + @Override public CacheObject prepareForCache(CacheObjectContext ctx) { + if (detached()) + return this; + + return detach(); + } + + /** {@inheritDoc} */ + @Override public void finishUnmarshal(CacheObjectContext ctx, ClassLoader ldr) throws IgniteCheckedException { + assert val != null || valBytes != null; + + if (val == null && ctx.storeValue()) + val = ctx.processor().unmarshal(ctx, valBytes, ldr); + } + + /** {@inheritDoc} */ + @Override public void prepareMarshal(CacheObjectContext ctx) throws IgniteCheckedException { + assert val != null || valBytes != null; + + toMarshaledFormIfNeeded(ctx); + } + + /** {@inheritDoc} */ + @Override public byte directType() { + // refer to GridIoMessageFactory. + return 113; + } + + /** {@inheritDoc} */ + @Override public byte type() { + return TYPE_OPTIMIZED; + } + + /** + * Checks whether a wrapped object has field with name {@code fieldName}. + * + * @param fieldName Field name. + * @param marsh Marshaller. + * @return {@code true} if has. + * @throws IgniteCheckedException In case of error. + */ + public boolean hasField(String fieldName, OptimizedMarshallerExt marsh) throws IgniteCheckedException { + assert valBytes != null; + + return marsh.hasField(fieldName, valBytes, start, len); + } + + /** + * Searches and returns field if it exists. + * + * @param fieldName Field name. + * @param marsh Marshaller. + * @return Field. + * @throws IgniteCheckedException In case of error. + */ + public Object field(String fieldName, OptimizedMarshallerExt marsh) throws IgniteCheckedException { + assert valBytes != null; + + return marsh.readField(fieldName, valBytes, start, len, val != null ? val.getClass().getClassLoader() : null); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + + out.writeInt(start); + out.writeInt(len); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + + start = in.readInt(); + len = in.readInt(); + } + + /** {@inheritDoc} */ + @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) { + reader.setBuffer(buf); + + if (!reader.beforeMessageRead()) + return false; + + if (!super.readFrom(buf, reader)) + return false; + + switch (reader.state()) { + case 1: + len = reader.readInt("len"); + + if (!reader.isLastRead()) + return false; + + reader.incrementState(); + + case 2: + start = reader.readInt("start"); + + if (!reader.isLastRead()) + return false; + + reader.incrementState(); + + } + + return true; + } + + /** {@inheritDoc} */ + @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) { + writer.setBuffer(buf); + + if (!super.writeTo(buf, writer)) + return false; + + if (!writer.isHeaderWritten()) { + if (!writer.writeHeader(directType(), fieldsCount())) + return false; + + writer.onHeaderWritten(); + } + + switch (writer.state()) { + case 1: + if (!writer.writeInt("len", len)) + return false; + + writer.incrementState(); + + case 2: + if (!writer.writeInt("start", start)) + return false; + + writer.incrementState(); + + } + + return true; + } + + /** {@inheritDoc} */ + @Override public byte fieldsCount() { + return 3; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + assert false; + + return super.hashCode(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + assert false; + + return super.equals(obj); + } + + /** + * Detaches object. + * + * @return Detached object wrapped by {@code CacheOptimizedObjectImpl}. + */ + protected CacheOptimizedObjectImpl detach() { + if (detached()) + return this; + + byte[] arr = new byte[len]; + + U.arrayCopy(valBytes, start, arr, 0, len); + + return new CacheOptimizedObjectImpl(arr, 0, len); + } + + /** + * Checks whether the object is already detached or not. + * + * @return {@code true} if detached. + */ + protected boolean detached() { + return start == 0 && len == valBytes.length; + } + + /** + * Marshals {@link #val} to {@link #valBytes} if needed. + * + * @param ctx Cache object context. + * @throws IgniteCheckedException In case of error. + */ + protected void toMarshaledFormIfNeeded(CacheObjectContext ctx) throws IgniteCheckedException { + if (valBytes == null) { + assert val != null; + + valBytes = ctx.processor().marshal(ctx, val); + + start = 0; + len = valBytes.length; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheOptimizedObjectImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheOptimizedObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheOptimizedObjectImpl.java new file mode 100644 index 0000000..8da074e --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheOptimizedObjectImpl.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.cache; + +import org.jetbrains.annotations.*; + +/** + * Cache object implementation for classes that support footer injection is their serialized form thus enabling fields + * search and extraction without necessity to fully deserialize an object. + */ +public class KeyCacheOptimizedObjectImpl extends CacheOptimizedObjectImpl implements KeyCacheObject { + /** */ + private static final long serialVersionUID = 0L; + + /** + * + */ + public KeyCacheOptimizedObjectImpl() { + // No-op + } + + /** + * @param val Object. + * @param valBytes Object in a serialized form. + */ + public KeyCacheOptimizedObjectImpl(Object val, byte[] valBytes) { + super(val, valBytes); + + assert val != null; + } + + /** + * @param val Object. + * @param valBytes Object in a serialized form. + * @param start Object's start in the array. + * @param len Object's len in the array. + */ + public KeyCacheOptimizedObjectImpl(Object val, byte[] valBytes, int start, int len) { + super(val, valBytes, start, len); + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) { + assert val != null; + + return (T)val; + } + + /** {@inheritDoc} */ + @Override public CacheObject prepareForCache(CacheObjectContext ctx) { + return this; + } + + /** {@inheritDoc} */ + @Override public byte directType() { + // refer to GridIoMessageFactory. + return 113; + } + + /** {@inheritDoc} */ + @Override public boolean internal() { + assert val != null; + + return val instanceof GridCacheInternal; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + assert val != null; + + return val.hashCode(); + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object obj) { + if (!(obj instanceof KeyCacheOptimizedObjectImpl)) + return false; + + KeyCacheOptimizedObjectImpl other = (KeyCacheOptimizedObjectImpl)obj; + + return val.equals(other.val); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java index 6a5f947..1afc2fe 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java @@ -22,6 +22,7 @@ import org.apache.ignite.configuration.*; import org.apache.ignite.internal.*; import org.apache.ignite.internal.processors.*; import org.apache.ignite.internal.processors.cache.*; +import org.apache.ignite.marshaller.optimized.ext.*; import org.jetbrains.annotations.*; /** @@ -97,15 +98,16 @@ public interface IgniteCacheObjectProcessor extends GridProcessor { public boolean hasField(Object obj, String fieldName); /** - * Checks whether a footer injection into a serialized form of the object is supported. - * Footer contains information on fields location in the serialized form, thus enabling fast queries without a need - * to deserialize the object. + * Checks whether fields indexing is supported by footer injection into a serialized form of the object. + * Footer contains information about fields location in the serialized form, thus enabling fast queries without + * a need to deserialize the object. + * + * Indexing is enabled with {@link OptimizedMarshallerExt#enableFieldsIndexing(Class)}. * * @param cls Class. * @return {@code true} if the footer is supported. - * @throws IgniteCheckedException If failed. */ - public boolean footerSupported(Class<?> cls) throws IgniteCheckedException; + public boolean isFieldsIndexingSupported(Class<?> cls); /** * @param ctx Cache object context. @@ -125,6 +127,18 @@ public interface IgniteCacheObjectProcessor extends GridProcessor { public Object unmarshal(CacheObjectContext ctx, byte[] bytes, ClassLoader clsLdr) throws IgniteCheckedException; /** + * @param ctx Context. + * @param bytes Bytes. + * @param off Offset. + * @param len Length. + * @param clsLdr Class loader. + * @return Unmarshalled object. + * @throws IgniteCheckedException If failed. + */ + public Object unmarshal(CacheObjectContext ctx, byte[] bytes, int off, int len, ClassLoader clsLdr) + throws IgniteCheckedException; + + /** * @param ccfg Cache configuration. * @return Cache object context. * @throws IgniteCheckedException If failed. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java index 7a89598..fbbc514 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java @@ -28,7 +28,6 @@ import org.apache.ignite.internal.util.*; import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.lang.*; import org.apache.ignite.marshaller.*; -import org.apache.ignite.marshaller.optimized.*; import org.apache.ignite.marshaller.optimized.ext.*; import org.jetbrains.annotations.*; @@ -161,6 +160,23 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme } /** {@inheritDoc} */ + @Override public Object unmarshal(CacheObjectContext ctx, byte[] bytes, int off, int len, + ClassLoader clsLdr) throws IgniteCheckedException { + if (optMarshExt != null) + return optMarshExt.unmarshal(bytes, off, len, clsLdr); + + else if (off > 0 || len != bytes.length) { + byte[] arr = new byte[len]; + + U.arrayCopy(bytes, off, arr, 0, len); + + bytes = arr; + } + + return unmarshal(ctx, bytes, clsLdr); + } + + /** {@inheritDoc} */ @Override @Nullable public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj) { if (obj instanceof KeyCacheObject) return (KeyCacheObject)obj; @@ -177,9 +193,11 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor") protected KeyCacheObject toCacheKeyObject0(Object obj, boolean userObj) { if (!userObj) - return new KeyCacheObjectImpl(obj, null); + return isFieldsIndexingSupported(obj.getClass()) ? new KeyCacheOptimizedObjectImpl(obj, null) : + new KeyCacheObjectImpl(obj, null); - return new UserKeyCacheObjectImpl(obj); + return isFieldsIndexingSupported(obj.getClass()) ? new UserKeyCacheOptimizedObjectImpl(obj) : + new UserKeyCacheObjectImpl(obj); } /** {@inheritDoc} */ @@ -216,16 +234,16 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme case CacheObject.TYPE_REGULAR: return new CacheObjectImpl(null, bytes); + + case CacheObject.TYPE_OPTIMIZED: + return new CacheOptimizedObjectImpl(bytes, 0, bytes.length); } throw new IllegalArgumentException("Invalid object type: " + type); } /** {@inheritDoc} */ - @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx, - @Nullable Object obj, - boolean userObj) - { + @Nullable @Override public CacheObject toCacheObject(CacheObjectContext ctx, @Nullable Object obj, boolean userObj){ if (obj == null || obj instanceof CacheObject) return (CacheObject)obj; @@ -250,9 +268,11 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme } if (!userObj) - return new CacheObjectImpl(obj, null); + return isFieldsIndexingSupported(obj.getClass()) ? new CacheOptimizedObjectImpl(obj) : + new CacheObjectImpl(obj, null); - return new UserCacheObjectImpl(obj, null); + return isFieldsIndexingSupported(obj.getClass()) ? new UserCacheOptimizedObjectImpl(obj, null) : + new UserCacheObjectImpl(obj, null); } /** {@inheritDoc} */ @@ -311,17 +331,39 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme /** {@inheritDoc} */ @Override public Object field(Object obj, String fieldName) { + if (obj instanceof CacheOptimizedObjectImpl) { + assert optMarshExt != null; + + try { + return ((CacheOptimizedObjectImpl)obj).field(fieldName, optMarshExt); + } + catch (IgniteCheckedException e) { + throw new IgniteException(e); + } + } + return null; } /** {@inheritDoc} */ @Override public boolean hasField(Object obj, String fieldName) { + if (obj instanceof CacheOptimizedObjectImpl) { + assert optMarshExt != null; + + try { + return ((CacheOptimizedObjectImpl)obj).hasField(fieldName, optMarshExt); + } + catch (IgniteCheckedException e) { + throw new IgniteException(e); + } + } + return false; } /** {@inheritDoc} */ - @Override public boolean footerSupported(Class<?> cls) throws IgniteCheckedException { - return optMarshExt != null && optMarshExt.metaSupported(cls); + @Override public boolean isFieldsIndexingSupported(Class<?> cls) { + return optMarshExt != null && optMarshExt.fieldsIndexingEnabled(cls); } /** @@ -420,6 +462,101 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme } /** + * Wraps value provided by user, must be serialized before stored in cache. + * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingSupported(Class)}. + */ + private static class UserCacheOptimizedObjectImpl extends CacheOptimizedObjectImpl { + /** */ + private static final long serialVersionUID = 0L; + + /** + * + */ + public UserCacheOptimizedObjectImpl() { + //No-op. + } + + /** + * @param val Value. + * @param valBytes Value bytes. + */ + public UserCacheOptimizedObjectImpl(Object val, byte[] valBytes) { + super(val, valBytes); + } + + /** {@inheritDoc} */ + @Nullable @Override public <T> T value(CacheObjectContext ctx, boolean cpy) { + return super.value(ctx, false); // Do not need copy since user value is not in cache. + } + + /** {@inheritDoc} */ + @Override public CacheObject prepareForCache(CacheObjectContext ctx) { + try { + toMarshaledFormIfNeeded(ctx); + + if (ctx.storeValue()) { + ClassLoader ldr = ctx.p2pEnabled() ? + IgniteUtils.detectClass(this.val).getClassLoader() : val.getClass().getClassLoader(); + + Object val = this.val != null && ctx.processor().immutable(this.val) ? this.val : + ctx.processor().unmarshal(ctx, valBytes, start, len, ldr); + + return new CacheOptimizedObjectImpl(val, valBytes, start, len); + } + + return new CacheOptimizedObjectImpl(null, valBytes, start, len); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to marshal object: " + val, e); + } + } + } + + /** + * Wraps key provided by user, must be serialized before stored in cache. + * Used by classes that support fields indexing. Refer to {@link #isFieldsIndexingSupported(Class)}. + */ + private static class UserKeyCacheOptimizedObjectImpl extends KeyCacheOptimizedObjectImpl { + /** */ + private static final long serialVersionUID = 0L; + + /** + * + */ + public UserKeyCacheOptimizedObjectImpl() { + //No-op. + } + + /** + * @param key Key. + */ + UserKeyCacheOptimizedObjectImpl(Object key) { + super(key, null); + } + + /** {@inheritDoc} */ + @Override public CacheObject prepareForCache(CacheObjectContext ctx) { + try { + if (!ctx.processor().immutable(val)) { + toMarshaledFormIfNeeded(ctx); + + ClassLoader ldr = ctx.p2pEnabled() ? + IgniteUtils.detectClassLoader(IgniteUtils.detectClass(this.val)) : U.gridClassLoader(); + + Object val = ctx.processor().unmarshal(ctx, valBytes, start, len, ldr); + + return new KeyCacheOptimizedObjectImpl(val, valBytes, start, len); + } + + return new KeyCacheOptimizedObjectImpl(val, valBytes, start, len); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to marshal object: " + val, e); + } + } + } + + /** * Wraps value provided by user, must be copied before stored in cache. */ private static class UserCacheObjectByteArrayImpl extends CacheObjectByteArrayImpl { http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/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 7d1cad0..c8a85b2 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 @@ -534,7 +534,7 @@ public class OptimizedObjectInputStream extends ObjectInputStream { } } - readFooter(cls); + skipFooter(cls); return obj; } @@ -936,12 +936,12 @@ public class OptimizedObjectInputStream extends ObjectInputStream { } /** - * Reads object footer from the underlying stream. + * Skips object footer from the underlying stream. * * @param cls Class. * @throws IOException In case of error. */ - protected void readFooter(Class<?> cls) throws IOException { + protected void skipFooter(Class<?> cls) throws IOException { // No-op } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java index 8636566..ddbb1e5 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExt.java @@ -63,21 +63,22 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { } /** - * Stores metadata information for the given {@link Class}. If the metadata is stored then a footer will be added - * during marshalling of an object of the given {@link Class} to the end of its serialized form. + * Enables fields indexing for the object of the given {@code cls}. + * + * If enabled then a footer will be added during marshalling of an object of the given {@code cls} to the end of + * its serialized form. * * @param cls Class. - * @return {@code true} if the metadata has been added successfully and the footer will be written to the end of - * Object's serialized form. + * @return {@code true} if fields indexing is enabled. * @throws IgniteCheckedException In case of error. */ - public boolean putMetaForClass(Class<?> cls) throws IgniteCheckedException { + public boolean enableFieldsIndexing(Class<?> cls) throws IgniteCheckedException { assert metaHandler != null; try { OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor(clsMap, cls, ctx, mapper); - if (desc.fields().fieldsIndexingSupported()) { + if (desc.fields() != null && desc.fields().fieldsIndexingSupported()) { if (metaHandler.metadata(desc.typeId()) != null) return true; @@ -100,17 +101,24 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { } /** - * Checks whether a metadata is stored for the given {@link Class}. If it's stored then a footer is injected into - * a serialized form of the object of this {@link Class}. - * Footer contains information on fields location in the serialized form, thus enabling fast queries without a need - * to deserialize the object. + * Checks whether fields indexing is enabled for objects of the given {@code cls}. * * @param cls Class. - * @return {@code true} if the metadata exists and the footer will be written to the end of Object's serialized - * form. + * @return {@code true} if fields indexing is enabled. */ - public boolean metaSupported(Class<?> cls) throws IgniteCheckedException { - return metaHandler.metadata(resolveTypeId(cls.getName(), mapper)) != null; + public boolean fieldsIndexingEnabled(Class<?> cls) { + if (cls == OptimizedObjectMetadataKey.class) + return false; + + try { + OptimizedClassDescriptor desc = OptimizedMarshallerUtils.classDescriptor(clsMap, cls, ctx, mapper); + + return desc.fields() != null && desc.fields().fieldsIndexingSupported() && + metaHandler.metadata(desc.typeId()) != null; + } + catch (IOException e) { + throw new IgniteException("Failed to load class description: " + cls); + } } /** {@inheritDoc} */ @@ -189,6 +197,21 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public <T> T unmarshal(byte[] arr, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { + return unmarshal(arr, 0, arr.length, clsLdr); + } + + /** + * Unmarshals object from byte array using given class loader and offset with len. + * + * @param <T> Type of unmarshalled object. + * @param arr Byte array. + * @param off Object's offset in the array. + * @param len Object's length in the array. + * @param clsLdr Class loader to use. + * @return Unmarshalled object. + * @throws IgniteCheckedException If unmarshalling failed. + */ + public <T> T unmarshal(byte[] arr, int off, int len, @Nullable ClassLoader clsLdr) throws IgniteCheckedException { assert arr != null; OptimizedObjectInputStreamExt objIn = null; @@ -198,7 +221,7 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { objIn.context(clsMap, ctx, mapper, clsLdr != null ? clsLdr : dfltClsLdr, metaHandler); - objIn.in().bytes(arr, arr.length); + objIn.in().bytes(arr, off, len); return (T)objIn.readObject(); } @@ -207,8 +230,8 @@ public class OptimizedMarshallerExt extends OptimizedMarshaller { } catch (ClassNotFoundException e) { throw new IgniteCheckedException("Failed to find class with given class loader for unmarshalling " + - "(make sure same version of all classes are available on all nodes or" + - " enable peer-class-loading): " + clsLdr, e); + "(make sure same version of all classes are available on all nodes or" + + " enable peer-class-loading): " + clsLdr, e); } finally { OptimizedObjectStreamExtRegistry.closeIn(objIn); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java index e3af580..977a988 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/OptimizedObjectInputStreamExt.java @@ -22,11 +22,10 @@ import org.apache.ignite.marshaller.*; import org.apache.ignite.marshaller.optimized.*; import java.io.*; -import java.util.*; import java.util.concurrent.*; -import static org.apache.ignite.marshaller.optimized.ext.OptimizedMarshallerExt.*; import static org.apache.ignite.marshaller.optimized.OptimizedMarshallerUtils.*; +import static org.apache.ignite.marshaller.optimized.ext.OptimizedMarshallerExt.*; /** @@ -55,7 +54,7 @@ public class OptimizedObjectInputStreamExt extends OptimizedObjectInputStream { } /** {@inheritDoc} */ - @Override protected void readFooter(Class<?> cls) throws IOException { + @Override protected void skipFooter(Class<?> cls) throws IOException { if (metaHandler.metadata(resolveTypeId(cls.getName(), mapper)) != null) { int footerLen = in.readInt(); @@ -116,10 +115,9 @@ public class OptimizedObjectInputStreamExt extends OptimizedObjectInputStream { if (range != null && range.start > 0) { in.position(range.start); - if (in.readByte() == SERIALIZABLE && metaHandler.metadata(in.readInt()) != null) { - //TODO: IGNITE-950. Optimization - don't create a copy of array, pass the old one with range. - field = (F)new CacheObjectImpl(null, Arrays.copyOfRange(in.array(), range.start, range.len)); - } + if (in.readByte() == SERIALIZABLE && metaHandler.metadata(in.readInt()) != null) + //Do we need to make a copy of array? + field = (F)new CacheOptimizedObjectImpl(in.array(), range.start, range.len); else { in.position(range.start); field = (F)readObject(); @@ -179,9 +177,7 @@ public class OptimizedObjectInputStreamExt extends OptimizedObjectInputStream { //object header len: 1 - for type, 4 - for type ID, 2 - for checksum. fieldOff += 1 + 4 + clsNameLen + 2; - FieldRange range = new FieldRange(fieldOff, info.len == VARIABLE_LEN ? in.readShort() : info.len); - - return range; + return new FieldRange(fieldOff, info.len == VARIABLE_LEN ? in.readShort() : info.len); } else fieldOff += info.len == VARIABLE_LEN ? in.readShort() : info.len; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/package-info.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/package-info.java b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/package-info.java index 294ef7f..84d1ce3 100644 --- a/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/package-info.java +++ b/modules/core/src/main/java/org/apache/ignite/marshaller/optimized/ext/package-info.java @@ -16,6 +16,6 @@ */ /** * <!-- Package description. --> - * Contains <b>extended</b> Optimized marshaller. + * Contains <b>extended</b> version of Optimized marshaller. */ package org.apache.ignite.marshaller.optimized.ext; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/99c88b7c/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExtSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExtSelfTest.java b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExtSelfTest.java index d663c55..9887b0b 100644 --- a/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExtSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/marshaller/optimized/ext/OptimizedMarshallerExtSelfTest.java @@ -22,8 +22,6 @@ import org.apache.ignite.marshaller.*; import org.apache.ignite.marshaller.optimized.*; import org.apache.ignite.testframework.junits.common.*; -import java.util.concurrent.*; - /** * Optimized marshaller self test. */ @@ -40,7 +38,7 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest public void testHasField() throws Exception { OptimizedMarshallerExt marsh = (OptimizedMarshallerExt)OptimizedMarshallerExtSelfTest.marsh; - assertTrue(marsh.putMetaForClass(TestObject.class)); + assertTrue(marsh.enableFieldsIndexing(TestObject.class)); TestObject testObj = new TestObject("World", 50); @@ -58,7 +56,7 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest public void testReadField() throws Exception { OptimizedMarshallerExt marsh = (OptimizedMarshallerExt)OptimizedMarshallerExtSelfTest.marsh; - assertTrue(marsh.putMetaForClass(TestObject.class)); + assertTrue(marsh.enableFieldsIndexing(TestObject.class)); TestObject testObj = new TestObject("World", 50); @@ -76,12 +74,12 @@ public class OptimizedMarshallerExtSelfTest extends OptimizedMarshallerSelfTest assertEquals(testObj.o2, o2); // Add metadata for the enclosed object. - assertTrue(marsh.putMetaForClass(TestObject2.class)); + assertTrue(marsh.enableFieldsIndexing(TestObject2.class)); arr = marsh.marshal(testObj); // Must be returned in a wrapped form, since metadata was added enabling the footer. - CacheObjectImpl cacheObject = marsh.readField("o2", arr, 0, arr.length, null); + CacheOptimizedObjectImpl cacheObject = marsh.readField("o2", arr, 0, arr.length, null); arr = cacheObject.valueBytes(null);