/* * 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.platform.cache.query; import java.util.Iterator; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.binary.BinaryRawWriterEx; import org.apache.ignite.internal.processors.cache.query.QueryCursorEx; import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget; import org.apache.ignite.internal.processors.platform.PlatformContext; import org.apache.ignite.internal.processors.platform.utils.PlatformUtils; /** * */ public abstract class PlatformAbstractQueryCursor<T> extends PlatformAbstractTarget implements AutoCloseable { /** Get multiple entries. */ private static final int OP_GET_ALL = 1; /** Get all entries. */ private static final int OP_GET_BATCH = 2; /** Get single entry. */ private static final int OP_GET_SINGLE = 3; /** Start iterating. */ private static final int OP_ITERATOR = 4; /** Close iterator. */ private static final int OP_ITERATOR_CLOSE = 5; /** Close iterator. */ private static final int OP_ITERATOR_HAS_NEXT = 6; /** Underlying cursor. */ private final QueryCursorEx<T> cursor; /** Batch size size. */ private final int batchSize; /** Underlying iterator. */ private Iterator<T> iter; /** * Constructor. * * @param platformCtx Context. * @param cursor Underlying cursor. * @param batchSize Batch size. */ public PlatformAbstractQueryCursor(PlatformContext platformCtx, QueryCursorEx<T> cursor, int batchSize) { super(platformCtx); this.cursor = cursor; this.batchSize = batchSize; } /** {@inheritDoc} */ @Override public void processOutStream(int type, final BinaryRawWriterEx writer) throws IgniteCheckedException { switch (type) { case OP_GET_BATCH: { assert iter != null : "iterator() has not been called"; try { int cntPos = writer.reserveInt(); int cnt = 0; while (cnt < batchSize && iter.hasNext()) { write(writer, iter.next()); cnt++; } writer.writeInt(cntPos, cnt); } catch (Exception err) { throw PlatformUtils.unwrapQueryException(err); } break; } case OP_GET_SINGLE: { assert iter != null : "iterator() has not been called"; try { if (iter.hasNext()) { write(writer, iter.next()); return; } } catch (Exception err) { throw PlatformUtils.unwrapQueryException(err); } throw new IgniteCheckedException("No more data available."); } case OP_GET_ALL: { try { int pos = writer.reserveInt(); Consumer<T> consumer = new Consumer<>(this, writer); cursor.getAll(consumer); writer.writeInt(pos, consumer.cnt); } catch (Exception err) { throw PlatformUtils.unwrapQueryException(err); } break; } default: super.processOutStream(type, writer); } } /** {@inheritDoc} */ @Override public long processInLongOutLong(int type, long val) throws IgniteCheckedException { switch (type) { case OP_ITERATOR: iter = cursor.iterator(); return TRUE; case OP_ITERATOR_CLOSE: cursor.close(); return TRUE; case OP_ITERATOR_HAS_NEXT: assert iter != null : "iterator() has not been called"; return iter.hasNext() ? TRUE : FALSE; } return super.processInLongOutLong(type, val); } /** {@inheritDoc} */ @Override public void close() throws Exception { cursor.close(); } /** * Write value to the stream. Extension point to perform conversions on the object before writing it. * * @param writer Writer. * @param val Value. */ protected abstract void write(BinaryRawWriterEx writer, T val); /** * Query cursor consumer. */ private static class Consumer<T> implements QueryCursorEx.Consumer<T> { /** Current query cursor. */ private final PlatformAbstractQueryCursor<T> cursor; /** Writer. */ private final BinaryRawWriterEx writer; /** Count. */ private int cnt; /** * Constructor. * * @param writer Writer. */ public Consumer(PlatformAbstractQueryCursor<T> cursor, BinaryRawWriterEx writer) { this.cursor = cursor; this.writer = writer; } /** {@inheritDoc} */ @Override public void consume(T val) throws IgniteCheckedException { cursor.write(writer, val); cnt++; } } }