Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-14312

Ignite Client: Cannot find metadata for object with compact footer using SQL queries having multiple ignite client instances connected to different clusters within same application

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Blocker
    • Resolution: Unresolved
    • Affects Version/s: 2.6, 2.7, 2.8, 2.9
    • Fix Version/s: None
    • Component/s: binary, sql
    • Labels:
      None
    • Flags:
      Patch, Important

      Description

      Application with multiple Ignite client instances connected to different clusters with enabled indexing module fails to deserialise SQL query response.

      This is the exception:

      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]
      

      The error has been identified: Injected BinaryContext is incorrect due to static use of JdbcUtils.serializer replaced by last IgniteH2Indexing instance on 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:

      
          @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);
                  }
              };
          }
      

      org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing:

      
       ... 
          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;
      
      ...
      }
      

      org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject:

      ...
          @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()));
          }
      

      org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2JavaObject:

      
      ...
      
          /** {@inheritDoc} */
          @Override public Value value(GridKernalContext ctx) {
              return ValueJavaObject.getNoCopy(null, b, H2Utils.getH2Datahandler(ctx));
          }
      

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              mnusan Manuel Núñez
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: