use of org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable in project ignite by apache.
the class GridMapQueryExecutor method onQueryRequest0.
/**
* @param node Node authored request.
* @param reqId Request ID.
* @param segmentId index segment ID.
* @param schemaName Schema name.
* @param qrys Queries to execute.
* @param cacheIds Caches which will be affected by these queries.
* @param topVer Topology version.
* @param partsMap Partitions map for unstable topology.
* @param parts Explicit partitions for current node.
* @param tbls Tables.
* @param pageSize Page size.
* @param distributedJoinMode Query distributed join mode.
*/
private void onQueryRequest0(ClusterNode node, long reqId, int segmentId, String schemaName, Collection<GridCacheSqlQuery> qrys, List<Integer> cacheIds, AffinityTopologyVersion topVer, Map<UUID, int[]> partsMap, int[] parts, Collection<QueryTable> tbls, int pageSize, DistributedJoinMode distributedJoinMode, boolean enforceJoinOrder, boolean replicated, int timeout, Object[] params) {
// Prepare to run queries.
GridCacheContext<?, ?> mainCctx = !F.isEmpty(cacheIds) ? ctx.cache().context().cacheContext(cacheIds.get(0)) : null;
NodeResults nodeRess = resultsForNode(node.id());
QueryResults qr = null;
List<GridReservable> reserved = new ArrayList<>();
try {
if (topVer != null) {
// Reserve primary for topology version or explicit partitions.
if (!reservePartitions(cacheIds, topVer, parts, reserved)) {
sendRetry(node, reqId, segmentId);
return;
}
}
qr = new QueryResults(reqId, qrys.size(), mainCctx != null ? mainCctx.name() : null);
if (nodeRess.put(reqId, segmentId, qr) != null)
throw new IllegalStateException();
// Prepare query context.
GridH2QueryContext qctx = new GridH2QueryContext(ctx.localNodeId(), node.id(), reqId, segmentId, replicated ? REPLICATED : MAP).filter(h2.backupFilter(topVer, parts)).partitionsMap(partsMap).distributedJoinMode(distributedJoinMode).pageSize(pageSize).topologyVersion(topVer).reservations(reserved);
List<GridH2Table> snapshotedTbls = null;
if (!F.isEmpty(tbls)) {
snapshotedTbls = new ArrayList<>(tbls.size());
for (QueryTable tbl : tbls) {
GridH2Table h2Tbl = h2.dataTable(tbl);
Objects.requireNonNull(h2Tbl, tbl.toString());
h2Tbl.snapshotIndexes(qctx, segmentId);
snapshotedTbls.add(h2Tbl);
}
}
Connection conn = h2.connectionForSchema(schemaName);
H2Utils.setupConnection(conn, distributedJoinMode != OFF, enforceJoinOrder);
GridH2QueryContext.set(qctx);
// qctx is set, we have to release reservations inside of it.
reserved = null;
try {
if (nodeRess.cancelled(reqId)) {
GridH2QueryContext.clear(ctx.localNodeId(), node.id(), reqId, qctx.type());
nodeRess.cancelRequest(reqId);
throw new QueryCancelledException();
}
// Run queries.
int qryIdx = 0;
boolean evt = mainCctx != null && ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED);
for (GridCacheSqlQuery qry : qrys) {
ResultSet rs = null;
// If we are not the target node for this replicated query, just ignore it.
if (qry.node() == null || (segmentId == 0 && qry.node().equals(ctx.localNodeId()))) {
rs = h2.executeSqlQueryWithTimer(conn, qry.query(), F.asList(qry.parameters(params)), true, timeout, qr.cancels[qryIdx]);
if (evt) {
assert mainCctx != null;
ctx.event().record(new CacheQueryExecutedEvent<>(node, "SQL query executed.", EVT_CACHE_QUERY_EXECUTED, CacheQueryType.SQL.name(), mainCctx.name(), null, qry.query(), null, null, params, node.id(), null));
}
assert rs instanceof JdbcResultSet : rs.getClass();
}
qr.addResult(qryIdx, qry, node.id(), rs, params);
if (qr.canceled) {
qr.result(qryIdx).close();
throw new QueryCancelledException();
}
// Send the first page.
sendNextPage(nodeRess, node, qr, qryIdx, segmentId, pageSize);
qryIdx++;
}
} finally {
GridH2QueryContext.clearThreadLocal();
if (distributedJoinMode == OFF)
qctx.clearContext(false);
if (!F.isEmpty(snapshotedTbls)) {
for (GridH2Table dataTbl : snapshotedTbls) dataTbl.releaseSnapshots();
}
}
} catch (Throwable e) {
if (qr != null) {
nodeRess.remove(reqId, segmentId, qr);
qr.cancel(false);
}
if (X.hasCause(e, GridH2RetryException.class))
sendRetry(node, reqId, segmentId);
else {
U.error(log, "Failed to execute local query.", e);
sendError(node, reqId, e);
if (e instanceof Error)
throw (Error) e;
}
} finally {
if (reserved != null) {
// Release reserved partitions.
for (int i = 0; i < reserved.size(); i++) reserved.get(i).release();
}
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable in project ignite by apache.
the class GridH2IndexBase method releaseSnapshot.
/**
* Releases snapshot for current thread.
*/
public void releaseSnapshot() {
Object s = snapshot.get();
assert s != null;
snapshot.remove();
if (s instanceof GridReservable)
((GridReservable) s).release();
if (s instanceof AutoCloseable)
U.closeQuiet((AutoCloseable) s);
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable in project ignite by apache.
the class GridMapQueryExecutor method onQueryRequest0.
/**
* @param node Node authored request.
* @param reqId Request ID.
* @param segmentId index segment ID.
* @param schemaName Schema name.
* @param qrys Queries to execute.
* @param cacheIds Caches which will be affected by these queries.
* @param topVer Topology version.
* @param partsMap Partitions map for unstable topology.
* @param parts Explicit partitions for current node.
* @param pageSize Page size.
* @param distributedJoinMode Query distributed join mode.
* @param lazy Streaming flag.
*/
private void onQueryRequest0(final ClusterNode node, final long reqId, final int segmentId, final String schemaName, final Collection<GridCacheSqlQuery> qrys, final List<Integer> cacheIds, final AffinityTopologyVersion topVer, final Map<UUID, int[]> partsMap, final int[] parts, final int pageSize, final DistributedJoinMode distributedJoinMode, final boolean enforceJoinOrder, final boolean replicated, final int timeout, final Object[] params, boolean lazy) {
if (lazy && MapQueryLazyWorker.currentWorker() == null) {
// Lazy queries must be re-submitted to dedicated workers.
MapQueryLazyWorkerKey key = new MapQueryLazyWorkerKey(node.id(), reqId, segmentId);
MapQueryLazyWorker worker = new MapQueryLazyWorker(ctx.igniteInstanceName(), key, log, this);
worker.submit(new Runnable() {
@Override
public void run() {
onQueryRequest0(node, reqId, segmentId, schemaName, qrys, cacheIds, topVer, partsMap, parts, pageSize, distributedJoinMode, enforceJoinOrder, replicated, timeout, params, true);
}
});
if (lazyWorkerBusyLock.enterBusy()) {
try {
MapQueryLazyWorker oldWorker = lazyWorkers.put(key, worker);
if (oldWorker != null)
oldWorker.stop();
IgniteThread thread = new IgniteThread(worker);
thread.start();
} finally {
lazyWorkerBusyLock.leaveBusy();
}
} else
log.info("Ignored query request (node is stopping) [nodeId=" + node.id() + ", reqId=" + reqId + ']');
return;
}
// Prepare to run queries.
GridCacheContext<?, ?> mainCctx = !F.isEmpty(cacheIds) ? ctx.cache().context().cacheContext(cacheIds.get(0)) : null;
MapNodeResults nodeRess = resultsForNode(node.id());
MapQueryResults qr = null;
List<GridReservable> reserved = new ArrayList<>();
try {
if (topVer != null) {
// Reserve primary for topology version or explicit partitions.
if (!reservePartitions(cacheIds, topVer, parts, reserved)) {
// Unregister lazy worker because re-try may never reach this node again.
if (lazy)
stopAndUnregisterCurrentLazyWorker();
sendRetry(node, reqId, segmentId);
return;
}
}
qr = new MapQueryResults(h2, reqId, qrys.size(), mainCctx, MapQueryLazyWorker.currentWorker());
if (nodeRess.put(reqId, segmentId, qr) != null)
throw new IllegalStateException();
// Prepare query context.
GridH2QueryContext qctx = new GridH2QueryContext(ctx.localNodeId(), node.id(), reqId, segmentId, replicated ? REPLICATED : MAP).filter(h2.backupFilter(topVer, parts)).partitionsMap(partsMap).distributedJoinMode(distributedJoinMode).pageSize(pageSize).topologyVersion(topVer).reservations(reserved);
Connection conn = h2.connectionForSchema(schemaName);
H2Utils.setupConnection(conn, distributedJoinMode != OFF, enforceJoinOrder);
GridH2QueryContext.set(qctx);
// qctx is set, we have to release reservations inside of it.
reserved = null;
try {
if (nodeRess.cancelled(reqId)) {
GridH2QueryContext.clear(ctx.localNodeId(), node.id(), reqId, qctx.type());
nodeRess.cancelRequest(reqId);
throw new QueryCancelledException();
}
// Run queries.
int qryIdx = 0;
boolean evt = mainCctx != null && mainCctx.events().isRecordable(EVT_CACHE_QUERY_EXECUTED);
for (GridCacheSqlQuery qry : qrys) {
ResultSet rs = null;
// If we are not the target node for this replicated query, just ignore it.
if (qry.node() == null || (segmentId == 0 && qry.node().equals(ctx.localNodeId()))) {
rs = h2.executeSqlQueryWithTimer(conn, qry.query(), F.asList(qry.parameters(params)), true, timeout, qr.queryCancel(qryIdx));
if (evt) {
ctx.event().record(new CacheQueryExecutedEvent<>(node, "SQL query executed.", EVT_CACHE_QUERY_EXECUTED, CacheQueryType.SQL.name(), mainCctx.name(), null, qry.query(), null, null, params, node.id(), null));
}
assert rs instanceof JdbcResultSet : rs.getClass();
}
qr.addResult(qryIdx, qry, node.id(), rs, params);
if (qr.cancelled()) {
qr.result(qryIdx).close();
throw new QueryCancelledException();
}
// Send the first page.
sendNextPage(nodeRess, node, qr, qryIdx, segmentId, pageSize);
qryIdx++;
}
// All request results are in the memory in result set already, so it's ok to release partitions.
if (!lazy)
releaseReservations();
} catch (Throwable e) {
releaseReservations();
throw e;
}
} catch (Throwable e) {
if (qr != null) {
nodeRess.remove(reqId, segmentId, qr);
qr.cancel(false);
}
// Unregister worker after possible cancellation.
if (lazy)
stopAndUnregisterCurrentLazyWorker();
if (X.hasCause(e, GridH2RetryException.class))
sendRetry(node, reqId, segmentId);
else {
U.error(log, "Failed to execute local query.", e);
sendError(node, reqId, e);
if (e instanceof Error)
throw (Error) e;
}
} finally {
if (reserved != null) {
// Release reserved partitions.
for (int i = 0; i < reserved.size(); i++) reserved.get(i).release();
}
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable in project ignite by apache.
the class RetryCauseMessageSelfTest method testNonCollocatedFailureMessage.
/**
* Failed to execute non-collocated query (will retry)
*/
@Test
public void testNonCollocatedFailureMessage() {
final GridMapQueryExecutor mapQryExec = GridTestUtils.getFieldValue(h2Idx, IgniteH2Indexing.class, "mapQryExec");
final ConcurrentMap<PartitionReservationKey, GridReservable> reservations = reservations(h2Idx);
GridTestUtils.setFieldValue(h2Idx, "mapQryExec", new MockGridMapQueryExecutor() {
@Override
public void onQueryRequest(ClusterNode node, GridH2QueryRequest qryReq) throws IgniteCheckedException {
final PartitionReservationKey grpKey = new PartitionReservationKey(ORG, null);
reservations.put(grpKey, new GridReservable() {
@Override
public boolean reserve() {
throw H2Utils.retryException("test retry exception");
}
@Override
public void release() {
}
});
startedExecutor.onQueryRequest(node, qryReq);
}
}.insertRealExecutor(mapQryExec));
SqlQuery<String, Person> qry = new SqlQuery<String, Person>(Person.class, JOIN_SQL).setArgs("Organization #0");
qry.setDistributedJoins(true);
try {
personCache.query(qry).getAll();
} catch (CacheException e) {
assertTrue(e.getMessage().contains("Failed to execute non-collocated query (will retry) ["));
return;
} finally {
GridTestUtils.setFieldValue(h2Idx, "mapQryExec", mapQryExec);
}
fail();
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable in project ignite by apache.
the class PartitionReservationManager method reservePartitions.
/**
* @param cacheIds Cache IDs.
* @param reqTopVer Topology version from request.
* @param explicitParts Explicit partitions list.
* @param nodeId Node ID.
* @param reqId Request ID.
* @return String which is null in case of success or with causeMessage if failed
* @throws IgniteCheckedException If failed.
*/
public PartitionReservation reservePartitions(@Nullable List<Integer> cacheIds, AffinityTopologyVersion reqTopVer, final int[] explicitParts, UUID nodeId, long reqId) throws IgniteCheckedException {
try (TraceSurroundings ignored = MTC.support(ctx.tracing().create(SQL_PARTITIONS_RESERVE, MTC.span()))) {
assert reqTopVer != null;
AffinityTopologyVersion topVer = ctx.cache().context().exchange().lastAffinityChangedTopologyVersion(reqTopVer);
if (F.isEmpty(cacheIds))
return new PartitionReservation(Collections.emptyList());
Collection<Integer> partIds;
if (explicitParts == null)
partIds = null;
else if (explicitParts.length == 0)
partIds = Collections.emptyList();
else {
partIds = new ArrayList<>(explicitParts.length);
for (int explicitPart : explicitParts) partIds.add(explicitPart);
}
List<GridReservable> reserved = new ArrayList<>();
for (int i = 0; i < cacheIds.size(); i++) {
GridCacheContext<?, ?> cctx = ctx.cache().context().cacheContext(cacheIds.get(i));
// Cache was not found, probably was not deployed yet.
if (cctx == null) {
return new PartitionReservation(reserved, String.format("Failed to reserve partitions for query (cache is not " + "found on local node) [localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, cacheId=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i)));
}
if (cctx.isLocal() || !cctx.rebalanceEnabled())
continue;
// For replicated cache topology version does not make sense.
final PartitionReservationKey grpKey = new PartitionReservationKey(cctx.name(), cctx.isReplicated() ? null : topVer);
GridReservable r = reservations.get(grpKey);
if (explicitParts == null && r != null) {
// Try to reserve group partition if any and no explicits.
if (r != REPLICATED_RESERVABLE) {
if (!r.reserve())
return new PartitionReservation(reserved, String.format("Failed to reserve partitions for query (group " + "reservation failed) [localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, cacheId=%s, " + "cacheName=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i), cctx.name()));
reserved.add(r);
MTC.span().addLog(() -> "Cache partitions were reserved " + r);
}
} else {
// Try to reserve partitions one by one.
int partsCnt = cctx.affinity().partitions();
if (cctx.isReplicated()) {
// Check all the partitions are in owning state for replicated cache.
if (r == null) {
// Check only once.
for (int p = 0; p < partsCnt; p++) {
GridDhtLocalPartition part = partition(cctx, p);
// We don't need to reserve partitions because they will not be evicted in replicated caches.
GridDhtPartitionState partState = part != null ? part.state() : null;
if (partState != OWNING)
return new PartitionReservation(reserved, String.format("Failed to reserve partitions for " + "query (partition of REPLICATED cache is not in OWNING state) [" + "localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, cacheId=%s, " + "cacheName=%s, part=%s, partFound=%s, partState=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i), cctx.name(), p, (part != null), partState));
}
// Mark that we checked this replicated cache.
reservations.putIfAbsent(grpKey, REPLICATED_RESERVABLE);
MTC.span().addLog(() -> "Cache partitions were reserved [cache=" + cctx.name() + ", partitions=[0.." + partsCnt + ']');
}
} else {
// Reserve primary partitions for partitioned cache (if no explicit given).
if (explicitParts == null)
partIds = cctx.affinity().primaryPartitions(ctx.localNodeId(), topVer);
int reservedCnt = 0;
for (int partId : partIds) {
GridDhtLocalPartition part = partition(cctx, partId);
GridDhtPartitionState partState = part != null ? part.state() : null;
if (partState != OWNING) {
if (partState == LOST)
failQueryOnLostData(cctx, part);
else {
return new PartitionReservation(reserved, String.format("Failed to reserve partitions " + "for query (partition of PARTITIONED cache is not found or not in OWNING " + "state) [localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, cacheId=%s, " + "cacheName=%s, part=%s, partFound=%s, partState=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i), cctx.name(), partId, (part != null), partState));
}
}
if (!part.reserve()) {
return new PartitionReservation(reserved, String.format("Failed to reserve partitions for query " + "(partition of PARTITIONED cache cannot be reserved) [" + "localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, cacheId=%s, " + "cacheName=%s, part=%s, partFound=%s, partState=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i), cctx.name(), partId, true, partState));
}
reserved.add(part);
reservedCnt++;
// Double check that we are still in owning state and partition contents are not cleared.
partState = part.state();
if (partState != OWNING) {
if (partState == LOST)
failQueryOnLostData(cctx, part);
else {
return new PartitionReservation(reserved, String.format("Failed to reserve partitions for " + "query (partition of PARTITIONED cache is not in OWNING state after " + "reservation) [localNodeId=%s, rmtNodeId=%s, reqId=%s, affTopVer=%s, " + "cacheId=%s, cacheName=%s, part=%s, partState=%s]", ctx.localNodeId(), nodeId, reqId, topVer, cacheIds.get(i), cctx.name(), partId, partState));
}
}
}
final Collection<Integer> finalPartIds = partIds;
MTC.span().addLog(() -> "Cache partitions were reserved [cache=" + cctx.name() + ", partitions=" + finalPartIds + ", topology=" + topVer + ']');
if (explicitParts == null && reservedCnt > 0) {
// We reserved all the primary partitions for cache, attempt to add group reservation.
GridDhtPartitionsReservation grp = new GridDhtPartitionsReservation(topVer, cctx, "SQL");
if (grp.register(reserved.subList(reserved.size() - reservedCnt, reserved.size()))) {
if (reservations.putIfAbsent(grpKey, grp) != null)
throw new IllegalStateException("Reservation already exists.");
grp.onPublish(new CI1<GridDhtPartitionsReservation>() {
@Override
public void apply(GridDhtPartitionsReservation r) {
reservations.remove(grpKey, r);
}
});
}
}
}
}
}
return new PartitionReservation(reserved);
}
}
Aggregations