com.datastax.driver.core.ExecutionInfo Maven / Gradle / Ivy
/*
* Copyright DataStax, Inc.
*
* This software can be used solely with DataStax Enterprise. Please consult the license at
* http://www.datastax.com/terms/datastax-dse-driver-license-terms
*/
package com.datastax.driver.core;
import com.datastax.driver.core.utils.Bytes;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/** Basic information on the execution of a query. */
public class ExecutionInfo {
private final int speculativeExecutions;
private final int successfulExecutionIndex;
private final List triedHosts;
private final ConsistencyLevel achievedConsistency;
private final QueryTrace trace;
private final ByteBuffer pagingState;
private final ProtocolVersion protocolVersion;
private final CodecRegistry codecRegistry;
private final Statement statement;
private volatile boolean schemaInAgreement;
private final List warnings;
private final Map incomingPayload;
private ExecutionInfo(
int speculativeExecutions,
int successfulExecutionIndex,
List triedHosts,
ConsistencyLevel achievedConsistency,
QueryTrace trace,
ByteBuffer pagingState,
ProtocolVersion protocolVersion,
CodecRegistry codecRegistry,
Statement statement,
boolean schemaAgreement,
List warnings,
Map incomingPayload) {
this.speculativeExecutions = speculativeExecutions;
this.successfulExecutionIndex = successfulExecutionIndex;
this.triedHosts = triedHosts;
this.achievedConsistency = achievedConsistency;
this.trace = trace;
this.pagingState = pagingState;
this.protocolVersion = protocolVersion;
this.codecRegistry = codecRegistry;
this.statement = statement;
this.schemaInAgreement = schemaAgreement;
this.warnings = warnings;
this.incomingPayload = incomingPayload;
}
ExecutionInfo(Host singleHost) {
this(
0,
0,
ImmutableList.of(singleHost),
null,
null,
null,
null,
null,
null,
true,
Collections.emptyList(),
null);
}
public ExecutionInfo(
int speculativeExecutions,
int successfulExecutionIndex,
List triedHosts,
ConsistencyLevel achievedConsistency,
Map customPayload) {
this(
speculativeExecutions,
successfulExecutionIndex,
triedHosts,
achievedConsistency,
null,
null,
null,
null,
null,
false,
null,
customPayload);
}
ExecutionInfo with(
QueryTrace newTrace,
List newWarnings,
ByteBuffer newPagingState,
Statement newStatement,
ProtocolVersion protocolVersion,
CodecRegistry codecRegistry) {
return new ExecutionInfo(
speculativeExecutions,
successfulExecutionIndex,
triedHosts,
achievedConsistency,
newTrace,
newPagingState,
protocolVersion,
codecRegistry,
newStatement,
schemaInAgreement,
newWarnings,
incomingPayload);
}
/**
* The list of tried hosts for this query.
*
* In general, this will be a singleton list with the host that coordinated that query.
* However:
*
*
* - if a host is tried by the driver but is dead or in error, that host is recorded and the
* query is retried;
*
- on a timeout or unavailable exception, some {@link
* com.datastax.driver.core.policies.RetryPolicy} may retry the query on the same host, so
* the same host might appear twice.
*
- if {@link com.datastax.driver.core.policies.SpeculativeExecutionPolicy speculative
* executions} are enabled, this will also contain hosts that were tried by other executions
* (however, note that this only contains hosts which timed out, or for which a response was
* received; if an execution is waiting for a response from a host and another execution
* completes the request in the meantime, then the host of the first execution will not be
* in that list).
*
*
* If you are only interested in fetching the final (and often only) node coordinating the
* query, {@link #getQueriedHost} provides a shortcut to fetch the last element of the list
* returned by this method.
*
* @return the list of tried hosts for this query, in the order tried.
*/
public List getTriedHosts() {
return triedHosts;
}
/**
* Return the Cassandra host that coordinated this query.
*
* This is a shortcut for {@code getTriedHosts().get(getTriedHosts().size() - 1)}.
*
* @return return the Cassandra host that coordinated this query.
*/
public Host getQueriedHost() {
return triedHosts.get(triedHosts.size() - 1);
}
/**
* The number of speculative executions that were started for this query.
*
*
This does not include the initial, normal execution of the query. Therefore, if speculative
* executions are disabled, this will always be 0. If they are enabled and one speculative
* execution was triggered in addition to the initial execution, this will be 1, etc.
*
* @see #getSuccessfulExecutionIndex()
* @see
* Cluster.Builder#withSpeculativeExecutionPolicy(com.datastax.driver.core.policies.SpeculativeExecutionPolicy)
*/
public int getSpeculativeExecutions() {
return speculativeExecutions;
}
/**
* The index of the execution that completed this query.
*
*
0 represents the initial, normal execution of the query, 1 represents the first speculative
* execution, etc.
*
* @see #getSpeculativeExecutions()
* @see
* Cluster.Builder#withSpeculativeExecutionPolicy(com.datastax.driver.core.policies.SpeculativeExecutionPolicy)
*/
public int getSuccessfulExecutionIndex() {
return successfulExecutionIndex;
}
/**
* If the query returned without achieving the requested consistency level due to the {@link
* com.datastax.driver.core.policies.RetryPolicy}, this return the biggest consistency level that
* has been actually achieved by the query.
*
*
Note that the default {@code RetryPolicy} ({@link
* com.datastax.driver.core.policies.DefaultRetryPolicy}) will never allow a query to be
* successful without achieving the initially requested consistency level and hence with that
* default policy, this method will always return {@code null}. However, it might
* occasionally return a non-{@code null} with say, {@link
* com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy}.
*
* @return {@code null} if the original consistency level of the query was achieved, or the
* consistency level that was ultimately achieved if the {@code RetryPolicy} triggered a retry
* at a different consistency level than the original one.
*/
public ConsistencyLevel getAchievedConsistencyLevel() {
return achievedConsistency;
}
/**
* Return the query trace if tracing was enabled on this query.
*
*
Note that accessing the fields of the the returned object will trigger a blocking
* background query.
*
* @return the {@code QueryTrace} object for this query if tracing was enable for this query, or
* {@code null} otherwise.
*/
public QueryTrace getQueryTrace() {
return trace;
}
/**
* Placeholder for async query trace retrieval (not implemented yet).
*
*
Async query trace retrieval will be implemented in a future version. This method is added
* now to avoid breaking binary compatibility later. The current implementation merely wraps the
* result of {@link #getQueryTrace()} in an immediate future; it will still trigger a blocking
* query when the query trace's fields are accessed.
*
* @return currently, an immediate future containing the result of {@link #getQueryTrace()}.
*/
public ListenableFuture getQueryTraceAsync() {
return Futures.immediateFuture(trace);
}
/**
* The paging state of the query.
*
* This object represents the next page to be fetched if this query is multi page. It can be
* saved and reused later on the same statement.
*
* @return the paging state or null if there is no next page.
* @see Statement#setPagingState(PagingState)
*/
public PagingState getPagingState() {
if (this.pagingState == null) return null;
return new PagingState(
this.pagingState, this.statement, this.protocolVersion, this.codecRegistry);
}
/**
* Returns the "raw" paging state of the query.
*
*
Contrary to {@link #getPagingState()}, there will be no validation when this is later
* reinjected into a statement.
*
* @return the paging state or null if there is no next page.
* @see Statement#setPagingStateUnsafe(byte[])
*/
public byte[] getPagingStateUnsafe() {
if (this.pagingState == null) return null;
return Bytes.getArray(this.pagingState);
}
/**
* Whether the cluster had reached schema agreement after the execution of this query.
*
*
After a successful schema-altering query (ex: creating a table), the driver will check if
* the cluster's nodes agree on the new schema version. If not, it will keep retrying for a given
* delay (configurable via {@link Cluster.Builder#withMaxSchemaAgreementWaitSeconds(int)}).
*
*
If this method returns {@code false}, clients can call {@link
* Metadata#checkSchemaAgreement()} later to perform the check manually.
*
*
Note that the schema agreement check is only performed for schema-altering queries For other
* query types, this method will always return {@code true}.
*
* @return whether the cluster reached schema agreement, or {@code true} for a non schema-altering
* statement.
*/
public boolean isSchemaInAgreement() {
return schemaInAgreement;
}
void setSchemaInAgreement(boolean schemaAgreement) {
this.schemaInAgreement = schemaAgreement;
}
/**
* Returns the server-side warnings for this query.
*
*
This feature is only available with {@link ProtocolVersion#V4} or above; with lower
* versions, the returned list will always be empty.
*
* @return the warnings, or an empty list if there are none.
* @since 2.2
*/
public List getWarnings() {
return warnings;
}
/**
* Return the incoming payload, that is, the payload that the server sent back with its response,
* if any, or {@code null}, if the server did not include any custom payload.
*
* This method returns a read-only view of the original map, but its values remain inherently
* mutable. Callers should take care not to modify the returned map in any way.
*
*
This feature is only available with {@link ProtocolVersion#V4} or above; with lower
* versions, this method will always return {@code null}.
*
* @return the custom payload that the server sent back with its response, if any, or {@code
* null}, if the server did not include any custom payload.
* @since 2.2
*/
public Map getIncomingPayload() {
return incomingPayload;
}
/**
* Get the statement that has been executed.
*
* @return the statement executed.
*/
public Statement getStatement() {
return this.statement;
}
}