blob: b493b5afa3520b4ade88ecc1f9106daab8658521 [file] [log] [blame]
/*
* 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.query.h2.twostep.msg;
import java.io.Externalizable;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.GridDirectCollection;
import org.apache.ignite.internal.GridDirectMap;
import org.apache.ignite.internal.GridDirectTransient;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteCodeGeneratingFail;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.binary.BinaryUtils;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
import org.apache.ignite.internal.processors.query.h2.QueryTable;
import org.apache.ignite.internal.processors.query.running.RunningQueryManager;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
import org.apache.ignite.plugin.extensions.communication.MessageReader;
import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import static org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery.EMPTY_PARAMS;
/**
* Query request.
*/
@IgniteCodeGeneratingFail
public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
/** */
private static final long serialVersionUID = 0L;
/**
* Map query will not destroy context until explicit query cancel request will be received because distributed join
* requests can be received.
*/
public static final int FLAG_DISTRIBUTED_JOINS = 1;
/**
* Remote map query executor will enforce join order for the received map queries.
*/
public static final int FLAG_ENFORCE_JOIN_ORDER = 1 << 1;
/**
* Whether to treat replicated as partitioned (for outer joins).
*/
public static final int FLAG_REPLICATED_AS_PARTITIONED = 1 << 2;
/**
* If it is an EXPLAIN command.
*/
public static final int FLAG_EXPLAIN = 1 << 3;
/**
* If it is a REPLICATED query.
*/
public static final int FLAG_REPLICATED = 1 << 4;
/**
* If lazy execution is enabled.
*/
public static final int FLAG_LAZY = 1 << 5;
/** */
private static final int FLAG_DATA_PAGE_SCAN_SHIFT = 6;
/** */
private static final int FLAG_DATA_PAGE_SCAN_MASK = 0b11 << FLAG_DATA_PAGE_SCAN_SHIFT;
/** */
@SuppressWarnings("PointlessBitwiseExpression")
private static final int FLAG_DATA_PAGE_SCAN_DFLT = 0b00 << FLAG_DATA_PAGE_SCAN_SHIFT;
/** */
private static final int FLAG_DATA_PAGE_SCAN_ENABLED = 0b01 << FLAG_DATA_PAGE_SCAN_SHIFT;
/** */
private static final int FLAG_DATA_PAGE_SCAN_DISABLED = 0b10 << FLAG_DATA_PAGE_SCAN_SHIFT;
/** */
private long reqId;
/** */
@GridToStringInclude
@GridDirectCollection(Integer.class)
private List<Integer> caches;
/** Topology version. */
private AffinityTopologyVersion topVer;
/** Explicit partitions mappings for nodes. */
@GridToStringInclude
@GridDirectMap(keyType = UUID.class, valueType = int[].class)
private Map<UUID, int[]> parts;
/** Query partitions. */
@GridToStringInclude
private int[] qryParts;
/** */
private int pageSize;
/** */
@GridToStringInclude
@GridDirectCollection(Message.class)
private List<GridCacheSqlQuery> qrys;
/** */
private byte flags;
/** */
@GridToStringInclude
@GridDirectCollection(Message.class)
private Collection<QueryTable> tbls;
/** */
private int timeout;
/** */
@GridToStringInclude(sensitive = true)
@GridDirectTransient
private Object[] params;
/** */
private byte[] paramsBytes;
/** Schema name. */
private String schemaName;
/** Id of the query assigned by {@link RunningQueryManager} on originator node. */
private long qryId;
/** */
private boolean explicitTimeout;
/**
* Required by {@link Externalizable}
*/
public GridH2QueryRequest() {
// No-op.
}
/**
* @param req Request.
*/
public GridH2QueryRequest(GridH2QueryRequest req) {
reqId = req.reqId;
caches = req.caches;
topVer = req.topVer;
parts = req.parts;
qryParts = req.qryParts;
pageSize = req.pageSize;
qrys = req.qrys;
flags = req.flags;
tbls = req.tbls;
timeout = req.timeout;
params = req.params;
paramsBytes = req.paramsBytes;
schemaName = req.schemaName;
qryId = req.qryId;
explicitTimeout = req.explicitTimeout;
}
/**
* @return Parameters.
*/
public Object[] parameters() {
return params;
}
/**
* @param params Parameters.
* @return {@code this}.
*/
public GridH2QueryRequest parameters(Object[] params) {
if (params == null)
params = EMPTY_PARAMS;
this.params = params;
return this;
}
/**
* @param tbls Tables.
* @return {@code this}.
*/
public GridH2QueryRequest tables(Collection<QueryTable> tbls) {
this.tbls = tbls;
return this;
}
/**
* Get tables.
* <p>
* N.B.: Was used in AI 1.9 for snapshots. Unused at the moment, but should be kept for compatibility reasons.
*
* @return Tables.
*/
public Collection<QueryTable> tables() {
return tbls;
}
/**
* @param reqId Request ID.
* @return {@code this}.
*/
public GridH2QueryRequest requestId(long reqId) {
this.reqId = reqId;
return this;
}
/**
* @return Request ID.
*/
public long requestId() {
return reqId;
}
/**
* @param caches Caches.
* @return {@code this}.
*/
public GridH2QueryRequest caches(List<Integer> caches) {
this.caches = caches;
return this;
}
/**
* @return Caches.
*/
public List<Integer> caches() {
return caches;
}
/**
* @param topVer Topology version.
* @return {@code this}.
*/
public GridH2QueryRequest topologyVersion(AffinityTopologyVersion topVer) {
this.topVer = topVer;
return this;
}
/**
* @return Topology version.
*/
public AffinityTopologyVersion topologyVersion() {
return topVer;
}
/**
* @return Explicit partitions mapping.
*/
public Map<UUID, int[]> partitions() {
return parts;
}
/**
* @param parts Explicit partitions mapping.
* @return {@code this}.
*/
public GridH2QueryRequest partitions(Map<UUID, int[]> parts) {
this.parts = parts;
return this;
}
/**
* @return Query partitions.
*/
public int[] queryPartitions() {
return qryParts;
}
/**
* @param qryParts Query partitions.
* @return {@code this}.
*/
public GridH2QueryRequest queryPartitions(int[] qryParts) {
this.qryParts = qryParts;
return this;
}
/**
* @param pageSize Page size.
* @return {@code this}.
*/
public GridH2QueryRequest pageSize(int pageSize) {
this.pageSize = pageSize;
return this;
}
/**
* @return Page size.
*/
public int pageSize() {
return pageSize;
}
/**
* @param qrys SQL Queries.
* @return {@code this}.
*/
public GridH2QueryRequest queries(List<GridCacheSqlQuery> qrys) {
this.qrys = qrys;
return this;
}
/**
* @return SQL Queries.
*/
public List<GridCacheSqlQuery> queries() {
return qrys;
}
/**
* @param flags Flags.
* @return {@code this}.
*/
public GridH2QueryRequest flags(int flags) {
assert flags >= 0 && flags <= 255 : flags;
this.flags = (byte)flags;
return this;
}
/**
* @param flags Flags to check.
* @return {@code true} If all the requested flags are set to {@code true}.
*/
public boolean isFlagSet(int flags) {
return (this.flags & flags) == flags;
}
/**
* @return Timeout.
*/
public int timeout() {
return timeout;
}
/**
* @param timeout New timeout.
* @return {@code this}.
*/
public GridH2QueryRequest timeout(int timeout) {
this.timeout = timeout;
return this;
}
/**
* @return {@code true} if query timeout is set explicitly.
*/
public boolean explicitTimeout() {
return explicitTimeout;
}
/**
* @param explicitTimeout Explicit timeout flag.
* @return {@code this}.
*/
public GridH2QueryRequest explicitTimeout(boolean explicitTimeout) {
this.explicitTimeout = explicitTimeout;
return this;
}
/**
* @return Schema name.
*/
public String schemaName() {
return schemaName;
}
/**
* @param schemaName Schema name.
* @return {@code this}.
*/
public GridH2QueryRequest schemaName(String schemaName) {
this.schemaName = schemaName;
return this;
}
/**
* @param flags Flags.
* @param dataPageScanEnabled {@code true} If data page scan enabled, {@code false} if not, and {@code null} if not set.
* @return Updated flags.
*/
public static int setDataPageScanEnabled(int flags, Boolean dataPageScanEnabled) {
int x = dataPageScanEnabled == null ? FLAG_DATA_PAGE_SCAN_DFLT :
dataPageScanEnabled ? FLAG_DATA_PAGE_SCAN_ENABLED : FLAG_DATA_PAGE_SCAN_DISABLED;
flags &= ~FLAG_DATA_PAGE_SCAN_MASK; // Clear old bits.
flags |= x; // Set new bits.
return flags;
}
/**
* Build query flags.
*
* @return Query flags.
*/
public static int queryFlags(boolean distributedJoins,
boolean enforceJoinOrder,
boolean lazy,
boolean replicatedOnly,
boolean explain,
Boolean dataPageScanEnabled,
boolean treatReplicatedAsPartitioned) {
int flags = enforceJoinOrder ? FLAG_ENFORCE_JOIN_ORDER : 0;
// Distributed joins flag is set if it is either reald
if (distributedJoins)
flags |= FLAG_DISTRIBUTED_JOINS;
if (explain)
flags |= FLAG_EXPLAIN;
if (replicatedOnly)
flags |= FLAG_REPLICATED;
if (lazy)
flags |= FLAG_LAZY;
flags = setDataPageScanEnabled(flags, dataPageScanEnabled);
if (treatReplicatedAsPartitioned)
flags |= FLAG_REPLICATED_AS_PARTITIONED;
return flags;
}
/**
* Id of the query assigned by {@link RunningQueryManager} on originator node.
*
* @return Query id.
*/
public long queryId() {
return qryId;
}
/**
* Sets id of the query assigned by {@link RunningQueryManager}.
*
* @param queryId Query id.
* @return {@code this} for chaining.
*/
public GridH2QueryRequest queryId(long queryId) {
this.qryId = queryId;
return this;
}
/**
* Checks if data page scan enabled.
*
* @return {@code true} If data page scan enabled, {@code false} if not, and {@code null} if not set.
*/
public Boolean isDataPageScanEnabled() {
return isDataPageScanEnabled(flags);
}
/**
* Checks if data page scan enabled.
*
* @param flags Flags.
* @return {@code true} If data page scan enabled, {@code false} if not, and {@code null} if not set.
*/
public static Boolean isDataPageScanEnabled(int flags) {
switch (flags & FLAG_DATA_PAGE_SCAN_MASK) {
case FLAG_DATA_PAGE_SCAN_ENABLED:
return true;
case FLAG_DATA_PAGE_SCAN_DISABLED:
return false;
}
return null;
}
/** {@inheritDoc} */
@Override public void marshall(Marshaller m) {
if (paramsBytes != null)
return;
assert params != null;
try {
paramsBytes = U.marshal(m, params);
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
/** {@inheritDoc} */
@SuppressWarnings("IfMayBeConditional")
@Override public void unmarshall(Marshaller m, GridKernalContext ctx) {
assert paramsBytes != null;
try {
final ClassLoader ldr = U.resolveClassLoader(ctx.config());
if (m instanceof BinaryMarshaller)
// To avoid deserializing of enum types.
params = BinaryUtils.rawArrayFromBinary(((BinaryMarshaller)m).binaryMarshaller().unmarshal(paramsBytes, ldr));
else
params = U.unmarshal(m, paramsBytes, ldr);
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
/** {@inheritDoc} */
@Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
writer.setBuffer(buf);
if (!writer.isHeaderWritten()) {
if (!writer.writeHeader(directType(), fieldsCount()))
return false;
writer.onHeaderWritten();
}
switch (writer.state()) {
case 0:
if (!writer.writeCollection("caches", caches, MessageCollectionItemType.INT))
return false;
writer.incrementState();
case 1:
if (!writer.writeByte("flags", flags))
return false;
writer.incrementState();
case 2:
if (!writer.writeInt("pageSize", pageSize))
return false;
writer.incrementState();
case 3:
if (!writer.writeByteArray("paramsBytes", paramsBytes))
return false;
writer.incrementState();
case 4:
if (!writer.writeMap("parts", parts, MessageCollectionItemType.UUID, MessageCollectionItemType.INT_ARR))
return false;
writer.incrementState();
case 5:
if (!writer.writeCollection("qrys", qrys, MessageCollectionItemType.MSG))
return false;
writer.incrementState();
case 6:
if (!writer.writeLong("reqId", reqId))
return false;
writer.incrementState();
case 7:
if (!writer.writeCollection("tbls", tbls, MessageCollectionItemType.MSG))
return false;
writer.incrementState();
case 8:
if (!writer.writeInt("timeout", timeout))
return false;
writer.incrementState();
case 9:
if (!writer.writeAffinityTopologyVersion("topVer", topVer))
return false;
writer.incrementState();
case 10:
if (!writer.writeIntArray("qryParts", qryParts))
return false;
writer.incrementState();
case 11:
if (!writer.writeString("schemaName", schemaName))
return false;
writer.incrementState();
case 12:
if (!writer.writeBoolean("explicitTimeout", explicitTimeout))
return false;
writer.incrementState();
case 13:
if (!writer.writeLong("qryId", qryId))
return false;
writer.incrementState();
}
return true;
}
/** {@inheritDoc} */
@Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
reader.setBuffer(buf);
if (!reader.beforeMessageRead())
return false;
switch (reader.state()) {
case 0:
caches = reader.readCollection("caches", MessageCollectionItemType.INT);
if (!reader.isLastRead())
return false;
reader.incrementState();
case 1:
flags = reader.readByte("flags");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 2:
pageSize = reader.readInt("pageSize");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 3:
paramsBytes = reader.readByteArray("paramsBytes");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 4:
parts = reader.readMap("parts", MessageCollectionItemType.UUID, MessageCollectionItemType.INT_ARR, false);
if (!reader.isLastRead())
return false;
reader.incrementState();
case 5:
qrys = reader.readCollection("qrys", MessageCollectionItemType.MSG);
if (!reader.isLastRead())
return false;
reader.incrementState();
case 6:
reqId = reader.readLong("reqId");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 7:
tbls = reader.readCollection("tbls", MessageCollectionItemType.MSG);
if (!reader.isLastRead())
return false;
reader.incrementState();
case 8:
timeout = reader.readInt("timeout");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 9:
topVer = reader.readAffinityTopologyVersion("topVer");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 10:
qryParts = reader.readIntArray("qryParts");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 11:
schemaName = reader.readString("schemaName");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 12:
explicitTimeout = reader.readBoolean("explicitTimeout");
if (!reader.isLastRead())
return false;
reader.incrementState();
case 13:
qryId = reader.readLong("qryId");
if (!reader.isLastRead())
return false;
reader.incrementState();
}
return reader.afterMessageRead(GridH2QueryRequest.class);
}
/** {@inheritDoc} */
@Override public short directType() {
return -33;
}
/** {@inheritDoc} */
@Override public byte fieldsCount() {
return 16;
}
/** {@inheritDoc} */
@Override public void onAckReceived() {
// No-op.
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridH2QueryRequest.class, this);
}
}