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

io.ebeaninternal.server.autotune.service.BaseQueryTuner Maven / Gradle / Ivy

There is a newer version: 15.8.1
Show newest version
package io.ebeaninternal.server.autotune.service;

import io.ebean.bean.CallStack;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.AutoTuneConfig;
import io.ebean.config.AutoTuneMode;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.autotune.ProfilingListener;
import io.ebeaninternal.server.autotune.model.Origin;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;

import javax.persistence.PersistenceException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 *
 */
public class BaseQueryTuner {

  private final boolean queryTuning;

  private final boolean profiling;

  private final AutoTuneMode mode;

  /**
   * Map of the tuned query details per profile query point.
   */
  private final Map tunedQueryInfoMap = new ConcurrentHashMap<>();

  private final SpiEbeanServer server;

  private final ProfilingListener profilingListener;

  /**
   * Flag set true when there is no profiling or query tuning.
   */
  private final boolean skipAll;

  public BaseQueryTuner(AutoTuneConfig config, SpiEbeanServer server, ProfilingListener profilingListener) {
    this.server = server;
    this.profilingListener = profilingListener;
    this.mode = config.getMode();
    this.queryTuning = config.isQueryTuning();
    this.profiling = config.isProfiling();
    this.skipAll = !queryTuning && !profiling;
  }

  /**
   * Return all the current tuned query entries.
   */
  public Collection getAll() {
    return tunedQueryInfoMap.values();
  }

  /**
   * Put a query tuning entry.
   */
  public void put(Origin origin) {

    tunedQueryInfoMap.put(origin.getKey(), new TunedQueryInfo(origin));
  }

  /**
   * Load the tuned query information.
   */
  public void load(String key, TunedQueryInfo queryInfo) {
    tunedQueryInfoMap.put(key, queryInfo);
  }

  /**
   * Return the detail currently used for tuning.
   * This returns null if there is currently no matching tuning.
   */
  public OrmQueryDetail get(String key) {
    TunedQueryInfo info = tunedQueryInfoMap.get(key);
    return (info == null) ? null : info.getTunedDetail();
  }

  /**
   * Auto tune the query and enable profiling.
   */
  public boolean tuneQuery(SpiQuery query) {

    if (skipAll || !tunableQuery(query)) {
      return false;
    }

    if (!useTuning(query)) {
      if (profiling) {
        profiling(query, server.createCallStack());
      }
      return false;
    }

    if (query.getParentNode() != null) {
      // This is a +lazy/+query query with profiling on.
      // We continue to collect the profiling information.
      query.setProfilingListener(profilingListener);
      return true;
    }

    // create a query point to identify the query
    CallStack stack = server.createCallStack();
    ObjectGraphNode origin = query.setOrigin(stack);

    if (profiling) {
      if (profilingListener.isProfileRequest(origin, query)) {
        // collect more profiling based on profiling rate etc
        query.setProfilingListener(profilingListener);
      }
    }

    if (queryTuning) {
      // get current "tuned fetch" for this query point
      TunedQueryInfo tuneInfo = tunedQueryInfoMap.get(origin.getOriginQueryPoint().getKey());
      return tuneInfo != null && tuneInfo.tuneQuery(query);
    }
    return false;
  }

  /**
   * Return false for row count, find ids, subQuery, delete and Versions queries.
   * 

* These queries are not applicable for autoTune in that they don't have a select/fetch (fetch group). *

*

* We also exclude queries that are explicitly set to load the L2 bean cache as we want full beans * in that case. *

*/ private boolean tunableQuery(SpiQuery query) { SpiQuery.Type type = query.getType(); switch (type) { case COUNT: case ID_LIST: case DELETE: case SUBQUERY: return false; default: // not using autoTune when explicitly loading the l2 bean cache // or when using Versions query return !query.isForceHitDatabase() && SpiQuery.TemporalMode.VERSIONS != query.getTemporalMode(); } } private void profiling(SpiQuery query, CallStack stack) { // create a query point to identify the query ObjectGraphNode origin = query.setOrigin(stack); if (profilingListener.isProfileRequest(origin, query)) { // collect more profiling based on profiling rate etc query.setProfilingListener(profilingListener); } } /** * Return true if we should try to tune this query. */ private boolean useTuning(SpiQuery query) { Boolean autoTune = query.isAutoTune(); if (autoTune != null) { // explicitly set... return autoTune; } else { // determine using implicit mode... switch (mode) { case DEFAULT_ON: return true; case DEFAULT_OFF: return false; case DEFAULT_ONIFEMPTY: return query.isDetailEmpty(); default: throw new PersistenceException("Invalid AutoTuneMode " + mode); } } } /** * Return the keys as a set. */ public Set keySet() { return tunedQueryInfoMap.keySet(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy