All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.driver.core.QueryOptions Maven / Gradle / Ivy

The newest version!
/*
 * Copyright DataStax, Inc.
 *
 * Licensed 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 com.datastax.driver.core;

import com.datastax.driver.core.exceptions.UnsupportedFeatureException;
import com.datastax.driver.core.utils.MoreFutures;
import com.datastax.driver.core.utils.MoreObjects;

/** Options related to defaults for individual queries. */
public class QueryOptions {

  /** The default consistency level for queries: {@link ConsistencyLevel#YB_STRONG}. */
  public static final ConsistencyLevel DEFAULT_CONSISTENCY_LEVEL = ConsistencyLevel.YB_STRONG;

  /**
   * The default serial consistency level for conditional updates: {@link ConsistencyLevel#SERIAL}.
   */
  public static final ConsistencyLevel DEFAULT_SERIAL_CONSISTENCY_LEVEL = ConsistencyLevel.SERIAL;

  /** The default fetch size for SELECT queries: 5000. */
  public static final int DEFAULT_FETCH_SIZE = 5000;

  /** The default value for {@link #getDefaultIdempotence()}: {@code false}. */
  public static final boolean DEFAULT_IDEMPOTENCE = false;

  public static final int DEFAULT_MAX_PENDING_REFRESH_NODE_LIST_REQUESTS = 20;

  public static final int DEFAULT_MAX_PENDING_REFRESH_NODE_REQUESTS = 20;

  public static final int DEFAULT_MAX_PENDING_REFRESH_SCHEMA_REQUESTS = 20;

  public static final int DEFAULT_REFRESH_NODE_LIST_INTERVAL_MILLIS = 1000;

  public static final int DEFAULT_REFRESH_NODE_INTERVAL_MILLIS = 1000;

  public static final int DEFAULT_REFRESH_SCHEMA_INTERVAL_MILLIS = 1000;

  private volatile ConsistencyLevel consistency = DEFAULT_CONSISTENCY_LEVEL;
  private volatile ConsistencyLevel serialConsistency = DEFAULT_SERIAL_CONSISTENCY_LEVEL;
  private volatile int fetchSize = DEFAULT_FETCH_SIZE;
  private volatile boolean defaultIdempotence = DEFAULT_IDEMPOTENCE;

  private volatile boolean consistencySet = false;
  private volatile boolean metadataEnabled = true;

  private volatile int maxPendingRefreshNodeListRequests =
      DEFAULT_MAX_PENDING_REFRESH_NODE_LIST_REQUESTS;
  private volatile int maxPendingRefreshNodeRequests = DEFAULT_MAX_PENDING_REFRESH_NODE_REQUESTS;
  private volatile int maxPendingRefreshSchemaRequests =
      DEFAULT_MAX_PENDING_REFRESH_SCHEMA_REQUESTS;

  private volatile int refreshNodeListIntervalMillis = DEFAULT_REFRESH_NODE_LIST_INTERVAL_MILLIS;
  private volatile int refreshNodeIntervalMillis = DEFAULT_REFRESH_NODE_INTERVAL_MILLIS;
  private volatile int refreshSchemaIntervalMillis = DEFAULT_REFRESH_SCHEMA_INTERVAL_MILLIS;

  private volatile boolean reprepareOnUp = true;
  private volatile Cluster.Manager manager;
  private volatile boolean prepareOnAllHosts = true;

  /**
   * Creates a new {@link QueryOptions} instance using the {@link #DEFAULT_CONSISTENCY_LEVEL},
   * {@link #DEFAULT_SERIAL_CONSISTENCY_LEVEL} and {@link #DEFAULT_FETCH_SIZE}.
   */
  public QueryOptions() {}

  void register(Cluster.Manager manager) {
    this.manager = manager;
  }

  /**
   * Sets the default consistency level to use for queries.
   *
   * 

The consistency level set through this method will be use for queries that don't explicitly * have a consistency level, i.e. when {@link Statement#getConsistencyLevel} returns {@code null}. * * @param consistencyLevel the new consistency level to set as default. * @return this {@code QueryOptions} instance. */ public QueryOptions setConsistencyLevel(ConsistencyLevel consistencyLevel) { this.consistencySet = true; this.consistency = consistencyLevel; return this; } /** * The default consistency level used by queries. * * @return the default consistency level used by queries. */ public ConsistencyLevel getConsistencyLevel() { return consistency; } /** * Sets the default serial consistency level to use for queries. * *

The serial consistency level set through this method will be use for queries that don't * explicitly have a serial consistency level, i.e. when {@link * Statement#getSerialConsistencyLevel} returns {@code null}. * * @param serialConsistencyLevel the new serial consistency level to set as default. * @return this {@code QueryOptions} instance. */ public QueryOptions setSerialConsistencyLevel(ConsistencyLevel serialConsistencyLevel) { this.serialConsistency = serialConsistencyLevel; return this; } /** * The default serial consistency level used by queries. * * @return the default serial consistency level used by queries. */ public ConsistencyLevel getSerialConsistencyLevel() { return serialConsistency; } /** * Sets the default fetch size to use for SELECT queries. * *

The fetch size set through this method will be use for queries that don't explicitly have a * fetch size, i.e. when {@link Statement#getFetchSize} is less or equal to 0. * * @param fetchSize the new fetch size to set as default. It must be strictly positive but you can * use {@code Integer.MAX_VALUE} to disable paging. * @return this {@code QueryOptions} instance. * @throws IllegalArgumentException if {@code fetchSize <e; 0}. * @throws UnsupportedFeatureException if version 1 of the native protocol is in use and {@code * fetchSize != Integer.MAX_VALUE} as paging is not supported by version 1 of the protocol. * See {@link Cluster.Builder#withProtocolVersion} for more details on protocol versions. */ public QueryOptions setFetchSize(int fetchSize) { if (fetchSize <= 0) throw new IllegalArgumentException("Invalid fetchSize, should be > 0, got " + fetchSize); ProtocolVersion version = manager == null ? null : manager.protocolVersion(); if (fetchSize != Integer.MAX_VALUE && version == ProtocolVersion.V1) throw new UnsupportedFeatureException(version, "Paging is not supported"); this.fetchSize = fetchSize; return this; } /** * The default fetch size used by queries. * * @return the default fetch size used by queries. */ public int getFetchSize() { return fetchSize; } /** * Sets the default idempotence for queries. * *

This will be used for statements for which {@link * com.datastax.driver.core.Statement#isIdempotent()} returns {@code null}. * * @param defaultIdempotence the new value to set as default idempotence. * @return this {@code QueryOptions} instance. */ public QueryOptions setDefaultIdempotence(boolean defaultIdempotence) { this.defaultIdempotence = defaultIdempotence; return this; } /** * The default idempotence for queries. * *

It defaults to {@link #DEFAULT_IDEMPOTENCE}. * * @return the default idempotence for queries. */ public boolean getDefaultIdempotence() { return defaultIdempotence; } /** * Set whether the driver should prepare statements on all hosts in the cluster. * *

A statement is normally prepared in two steps: * *

    *
  1. prepare the query on a single host in the cluster; *
  2. if that succeeds, prepare on all other hosts. *
* * This option controls whether step 2 is executed. It is enabled by default. * *

The reason why you might want to disable it is to optimize network usage if you have a large * number of clients preparing the same set of statements at startup. If your load balancing * policy distributes queries randomly, each client will pick a different host to prepare its * statements, and on the whole each host has a good chance of having been hit by at least one * client for each statement. * *

On the other hand, if that assumption turns out to be wrong and one host hasn't prepared a * given statement, it needs to be re-prepared on the fly the first time it gets executed; this * causes a performance penalty (one extra roundtrip to resend the query to prepare, and another * to retry the execution). * * @param prepareOnAllHosts the new value to set to indicate whether to prepare statements once or * on all nodes. * @return this {@code QueryOptions} instance. */ public QueryOptions setPrepareOnAllHosts(boolean prepareOnAllHosts) { this.prepareOnAllHosts = prepareOnAllHosts; return this; } /** * Returns whether the driver should prepare statements on all hosts in the cluster. * * @return the value. * @see #setPrepareOnAllHosts(boolean) */ public boolean isPrepareOnAllHosts() { return this.prepareOnAllHosts; } /** * Set whether the driver should re-prepare all cached prepared statements on a host when it marks * it back up. * *

This option is enabled by default. * *

The reason why you might want to disable it is to optimize reconnection time when you * believe hosts often get marked down because of temporary network issues, rather than the host * really crashing. In that case, the host still has prepared statements in its cache when the * driver reconnects, so re-preparing is redundant. * *

On the other hand, if that assumption turns out to be wrong and the host had really * restarted, its prepared statement cache is empty, and statements need to be re-prepared on the * fly the first time they get executed; this causes a performance penalty (one extra roundtrip to * resend the query to prepare, and another to retry the execution). * * @param reprepareOnUp whether the driver should re-prepare when marking a node up. * @return this {@code QueryOptions} instance. */ public QueryOptions setReprepareOnUp(boolean reprepareOnUp) { this.reprepareOnUp = reprepareOnUp; return this; } /** * Whether the driver should re-prepare all cached prepared statements on a host when its marks * that host back up. * * @return the value. * @see #setReprepareOnUp(boolean) */ public boolean isReprepareOnUp() { return this.reprepareOnUp; } /** * Toggle client-side token and schema metadata. * *

This feature is enabled by default. Some applications might wish to disable it in order to * eliminate the overhead of querying the metadata and building its client-side representation. * However, take note that doing so will have important consequences: * *

    *
  • most schema- or token-related methods in {@link Metadata} will return stale or null/empty * results (see the javadoc of each method for details); *
  • {@link Metadata#newToken(String)} and {@link Metadata#newTokenRange(Token, Token)} will * throw an exception if metadata was disabled before startup; *
  • token-aware routing will not work properly: if metadata was never initialized, {@link * com.datastax.driver.core.policies.TokenAwarePolicy} will always delegate to its child * policy. Otherwise, it might not pick the best coordinator (i.e. chose a host that is not * a replica for the statement's routing key). In addition, statements prepared while the * metadata was disabled might also be sent to a non-optimal coordinator, even if metadata * was re-enabled later. *
* * @param enabled whether metadata is enabled. * @return this {@code QueryOptions} instance. */ public QueryOptions setMetadataEnabled(boolean enabled) { boolean wasEnabled = this.metadataEnabled; this.metadataEnabled = enabled; if (!wasEnabled && enabled && manager != null) { // This is roughly the same as what we do in ControlConnection.tryConnect(): // 1. call submitNodeListRefresh() first to // be able to compute the token map for the first time, // which will be incomplete due to the lack of keyspace metadata GuavaCompatibility.INSTANCE.addCallback( manager.submitNodeListRefresh(), new MoreFutures.SuccessCallback() { @Override public void onSuccess(Void result) { // 2. then call submitSchemaRefresh() to // refresh schema metadata and re-compute the token map // this time with information about keyspaces manager.submitSchemaRefresh(null, null, null, null); } }); } return this; } /** * Whether client-side token and schema metadata is enabled. * * @return the value. * @see #setMetadataEnabled(boolean) */ public boolean isMetadataEnabled() { return metadataEnabled; } /** * Sets the default window size in milliseconds used to debounce node list refresh requests. * *

When the control connection receives a new schema refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; when a timer expires, then the pending * requests are coalesced and executed as a single request. * * @param refreshSchemaIntervalMillis The default window size in milliseconds used to debounce * schema refresh requests. */ public QueryOptions setRefreshSchemaIntervalMillis(int refreshSchemaIntervalMillis) { this.refreshSchemaIntervalMillis = refreshSchemaIntervalMillis; return this; } /** * The default window size in milliseconds used to debounce schema refresh requests. * * @return The default window size in milliseconds used to debounce schema refresh requests. */ public int getRefreshSchemaIntervalMillis() { return refreshSchemaIntervalMillis; } /** * Sets the maximum number of schema refresh requests that the control connection can accumulate * before executing them. * *

When the control connection receives a new schema refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; if the control connection receives too * many events, is parameter allows to trigger execution of pending requests, event if the last * timer is still running. * * @param maxPendingRefreshSchemaRequests The maximum number of schema refresh requests that the * control connection can accumulate before executing them. */ public QueryOptions setMaxPendingRefreshSchemaRequests(int maxPendingRefreshSchemaRequests) { this.maxPendingRefreshSchemaRequests = maxPendingRefreshSchemaRequests; return this; } /** * The maximum number of schema refresh requests that the control connection can accumulate before * executing them. * * @return The maximum number of schema refresh requests that the control connection can * accumulate before executing them. */ public int getMaxPendingRefreshSchemaRequests() { return maxPendingRefreshSchemaRequests; } /** * Sets the default window size in milliseconds used to debounce node list refresh requests. * *

When the control connection receives a new node list refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; when a timer expires, then the pending * requests are coalesced and executed as a single request. * * @param refreshNodeListIntervalMillis The default window size in milliseconds used to debounce * node list refresh requests. */ public QueryOptions setRefreshNodeListIntervalMillis(int refreshNodeListIntervalMillis) { this.refreshNodeListIntervalMillis = refreshNodeListIntervalMillis; return this; } /** * The default window size in milliseconds used to debounce node list refresh requests. * * @return The default window size in milliseconds used to debounce node list refresh requests. */ public int getRefreshNodeListIntervalMillis() { return refreshNodeListIntervalMillis; } /** * Sets the maximum number of node list refresh requests that the control connection can * accumulate before executing them. * *

When the control connection receives a new node list refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; if the control connection receives too * many events, is parameter allows to trigger execution of pending requests, event if the last * timer is still running. * * @param maxPendingRefreshNodeListRequests The maximum number of node list refresh requests that * the control connection can accumulate before executing them. */ public QueryOptions setMaxPendingRefreshNodeListRequests(int maxPendingRefreshNodeListRequests) { this.maxPendingRefreshNodeListRequests = maxPendingRefreshNodeListRequests; return this; } /** * Sets the maximum number of node list refresh requests that the control connection can * accumulate before executing them. * * @return The maximum number of node list refresh requests that the control connection can * accumulate before executing them. */ public int getMaxPendingRefreshNodeListRequests() { return maxPendingRefreshNodeListRequests; } /** * Sets the default window size in milliseconds used to debounce node refresh requests. * *

When the control connection receives a new node refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; when a timer expires, then the pending * requests are coalesced and executed as a single request. * * @param refreshNodeIntervalMillis The default window size in milliseconds used to debounce node * refresh requests. */ public QueryOptions setRefreshNodeIntervalMillis(int refreshNodeIntervalMillis) { this.refreshNodeIntervalMillis = refreshNodeIntervalMillis; return this; } /** * The default window size in milliseconds used to debounce node refresh requests. * * @return The default window size in milliseconds used to debounce node refresh requests. */ public int getRefreshNodeIntervalMillis() { return refreshNodeIntervalMillis; } /** * Sets the maximum number of node refresh requests that the control connection can accumulate * before executing them. * *

When the control connection receives a new node refresh request, it puts it on hold and * starts a timer, cancelling any previous running timer; if the control connection receives too * many events, is parameter allows to trigger execution of pending requests, event if the last * timer is still running. * * @param maxPendingRefreshNodeRequests The maximum number of node refresh requests that the * control connection can accumulate before executing them. */ public QueryOptions setMaxPendingRefreshNodeRequests(int maxPendingRefreshNodeRequests) { this.maxPendingRefreshNodeRequests = maxPendingRefreshNodeRequests; return this; } /** * The maximum number of node refresh requests that the control connection can accumulate before * executing them. * * @return The maximum number of node refresh requests that the control connection can accumulate * before executing them. */ public int getMaxPendingRefreshNodeRequests() { return maxPendingRefreshNodeRequests; } @Override public boolean equals(Object that) { if (that == null || !(that instanceof QueryOptions)) { return false; } QueryOptions other = (QueryOptions) that; return (this.consistency.equals(other.consistency) && this.serialConsistency.equals(other.serialConsistency) && this.fetchSize == other.fetchSize && this.defaultIdempotence == other.defaultIdempotence && this.metadataEnabled == other.metadataEnabled && this.maxPendingRefreshNodeListRequests == other.maxPendingRefreshNodeListRequests && this.maxPendingRefreshNodeRequests == other.maxPendingRefreshNodeRequests && this.maxPendingRefreshSchemaRequests == other.maxPendingRefreshSchemaRequests && this.refreshNodeListIntervalMillis == other.refreshNodeListIntervalMillis && this.refreshNodeIntervalMillis == other.refreshNodeIntervalMillis && this.refreshSchemaIntervalMillis == other.refreshSchemaIntervalMillis && this.reprepareOnUp == other.reprepareOnUp && this.prepareOnAllHosts == other.prepareOnAllHosts); } @Override public int hashCode() { return MoreObjects.hashCode( consistency, serialConsistency, fetchSize, defaultIdempotence, metadataEnabled, maxPendingRefreshNodeListRequests, maxPendingRefreshNodeRequests, maxPendingRefreshSchemaRequests, refreshNodeListIntervalMillis, refreshNodeIntervalMillis, refreshSchemaIntervalMillis, reprepareOnUp, prepareOnAllHosts); } public boolean isConsistencySet() { return consistencySet; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy