Manuel Núñez created IGNITE-14312:
-------------------------------------
Summary: Ignite Client: Cannot find metadata for object with
compact footer
Key: IGNITE-14312
URL: https://issues.apache.org/jira/browse/IGNITE-14312
Project: Ignite
Issue Type: Bug
Components: binary
Affects Versions: 2.9, 2.8, 2.7, 2.6
Reporter: Manuel Núñez
Application with multiple Ignite client instances connected to different
clusters with indexing module enable fails to reduce queries.
This is the exception:
{code:java}
Caused by: org.apache.ignite.binary.BinaryObjectException: Cannot find metadata
for object with compact footer (Ignite work directory might have been cleared
after restart. Make sure that IGNITE_HOME does not point to a temp folder or
any other folder that is destroyed/cleared on restarts) [typeId=-1468802099,
schemaId=360499151, IGNITE_HOME=/opt/ignite]
at
org.apache.ignite.internal.binary.BinaryReaderExImpl.getOrCreateSchema(BinaryReaderExImpl.java:2026)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.binary.BinaryReaderExImpl.<init>(BinaryReaderExImpl.java:293)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.binary.BinaryReaderExImpl.<init>(BinaryReaderExImpl.java:188)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.binary.BinaryObjectImpl.reader(BinaryObjectImpl.java:826)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.binary.BinaryObjectImpl.deserializeValue(BinaryObjectImpl.java:789)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.binary.BinaryObjectImpl.value(BinaryObjectImpl.java:142)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinary(CacheObjectUtils.java:176)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinaryIfNeeded(CacheObjectUtils.java:67)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinariesIfNeeded(CacheObjectUtils.java:135)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.cache.CacheObjectUtils.unwrapBinariesIfNeeded(CacheObjectUtils.java:77)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator.next(GridQueryCacheObjectsIterator.java:66)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator.next(GridQueryCacheObjectsIterator.java:31)
~[ignite-core-2.8.1.jar!/:2.8.1]
at
org.apache.ignite.internal.processors.cache.AutoClosableCursorIterator.next(AutoClosableCursorIterator.java:59)
~[ignite-core-2.8.1.jar!/:2.8.1]
{code}
The error has been identified: Injected BinaryContext is invalid due to static
use of JdbcUtils.serializer replaced into IgniteH2Indexing start method.
Solution: Use h2 DataHandler associated to GridKernalContext when calling
ValueJavaObject.getNoCopy, this avoid using static Jdbc.serializer instance
that could be eventually incorrect.
Proposal. Some simple changes into:
org.apache.ignite.internal.processors.query.h2.H2Utils
org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing
org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2JavaObject
org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject
org.apache.ignite.internal.processors.query.h2.H2Utils:
{code:java}
@SuppressWarnings("ConstantConditions")
public static Value wrap(CacheObjectValueContext coCtx, Object obj, int
type) throws IgniteCheckedException {
assert obj != null;
....
case Value.JAVA_OBJECT:
return ValueJavaObject.getNoCopy(obj, null, coCtx == null ?
null: H2Utils.getH2Datahandler(coCtx.kernalContext()));
...
}
public static DataHandler getH2Datahandler(GridKernalContext ctx) {
if (ctx == null)
return null;
return ((IgniteH2Indexing)ctx.query().getIndexing()).h2Datahandler();
}
public static JavaObjectSerializer getH2Serializer(GridKernalContext ctx) {
if (ctx == null)
return null;
return ((IgniteH2Indexing)ctx.query().getIndexing()).h2Serializer();
}
public static DataHandler createH2Datahandler(GridKernalContext ctx) {
return createH2Datahandler(createH2Serializer(ctx));
}
public static DataHandler createH2Datahandler(JavaObjectSerializer
serializer) {
return new DataHandler() {
@Override
public String getDatabasePath() {
throw new UnsupportedOperationException();
}
@Override
public FileStore openFile(String name, String mode, boolean
mustExist) {
throw new UnsupportedOperationException();
}
@Override
public void checkPowerOff() throws DbException {
throw new UnsupportedOperationException();
}
@Override
public void checkWritingAllowed() throws DbException {
throw new UnsupportedOperationException();
}
@Override
public int getMaxLengthInplaceLob() {
throw new UnsupportedOperationException();
}
@Override
public String getLobCompressionAlgorithm(int type) {
throw new UnsupportedOperationException();
}
@Override
public TempFileDeleter getTempFileDeleter() {
throw new UnsupportedOperationException();
}
@Override
public Object getLobSyncObject() {
throw new UnsupportedOperationException();
}
@Override
public SmallLRUCache<String, String[]> getLobFileListCache() {
throw new UnsupportedOperationException();
}
@Override
public LobStorageInterface getLobStorage() {
throw new UnsupportedOperationException();
}
@Override
public int readLob(long lobId, byte[] hmac, long offset, byte[]
buff, int off, int length) {
throw new UnsupportedOperationException();
}
@Override
public JavaObjectSerializer getJavaObjectSerializer() {
return serializer;
}
@Override
public CompareMode getCompareMode() {
throw new UnsupportedOperationException();
}
};
}
public static JavaObjectSerializer createH2Serializer(GridKernalContext
ctx) {
return new JavaObjectSerializer() {
@Override
public byte[] serialize(Object obj) throws Exception {
return U.marshal(ctx.config().getMarshaller(), obj);
}
@Override
public Object deserialize(byte[] bytes) throws Exception {
ClassLoader clsLdr = ctx != null ?
U.resolveClassLoader(ctx.config()) : null;
return U.unmarshal(ctx.config().getMarshaller(), bytes, clsLdr);
}
};
}
{code}
org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing:
{code:java}
...
private volatile DataHandler h2Datahandler;
private volatile JavaObjectSerializer h2Serializer;
...
/**
* @return H2 datahandler.
*/
public DataHandler h2Datahandler(){
return h2Datahandler;
}
/**
* @return H2 serializer.
*/
public JavaObjectSerializer h2Serializer(){
return h2Serializer;
}
@Override public void start(GridKernalContext ctx, GridSpinBusyLock
busyLock) throws IgniteCheckedException {
...
h2Serializer = H2Utils.createH2Serializer(ctx);
h2Datahandler = H2Utils.createH2Datahandler(h2Serializer);
if (JdbcUtils.serializer != null)
U.warn(log, "Custom H2 serialization is already configured, will
override.");
JdbcUtils.serializer = h2Serializer;
...
}
{code}
org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject:
{code:java}
...
@Override public byte[] getBytesNoCopy() {
if (obj.cacheObjectType() == CacheObject.TYPE_REGULAR) {
// Result must be the same as `marshaller.marshall(obj.value(coctx,
false));`
try {
return obj.valueBytes(valCtx);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
}
}
// For user-provided and array types.
return JdbcUtils.serialize(obj, valCtx == null ? null:
H2Utils.getH2Datahandler(valCtx.kernalContext()));
}
{code}
org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2JavaObject:
{code:java}
...
/** {@inheritDoc} */
@Override public Value value(GridKernalContext ctx) {
return ValueJavaObject.getNoCopy(null, b,
H2Utils.getH2Datahandler(ctx));
}
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)