mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
186 lines
4.4 KiB
Java
186 lines
4.4 KiB
Java
package com.avaje.ebeaninternal.server.autofetch;
|
|
|
|
import java.io.Serializable;
|
|
|
|
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
|
import com.avaje.ebeaninternal.api.SpiQuery;
|
|
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
|
|
|
/**
|
|
* Holds tuned query information. Is immutable so this represents the tuning at
|
|
* a given point in time.
|
|
*/
|
|
public class TunedQueryInfo implements Serializable {
|
|
|
|
private static final long serialVersionUID = 7381493228797997282L;
|
|
|
|
private final ObjectGraphOrigin origin;
|
|
|
|
/**
|
|
* The tuned query details with joins and properties.
|
|
*/
|
|
private OrmQueryDetail tunedDetail;
|
|
|
|
/**
|
|
* The number of times profiling has been collected for this query point.
|
|
*/
|
|
private int profileCount;
|
|
|
|
private Long lastTuneTime = Long.valueOf(0);
|
|
|
|
private final String rateMonitor = new String();
|
|
|
|
/**
|
|
* The number of queries tuned by this object.
|
|
* Could use AtomicInteger perhaps.
|
|
*/
|
|
private transient int tunedCount;
|
|
|
|
private transient int rateTotal;
|
|
|
|
private transient int rateHits;
|
|
|
|
private transient double lastRate;
|
|
|
|
public TunedQueryInfo(ObjectGraphOrigin queryPoint, OrmQueryDetail tunedDetail, int profileCount) {
|
|
this.origin = queryPoint;
|
|
this.tunedDetail = tunedDetail;
|
|
this.profileCount = profileCount;
|
|
}
|
|
|
|
/**
|
|
* Return true if this query should be profiled based on a percentage rate.
|
|
*/
|
|
public boolean isPercentageProfile(double rate) {
|
|
|
|
synchronized (rateMonitor) {
|
|
|
|
if (lastRate != rate) {
|
|
// the rate has changed so resetting
|
|
lastRate = rate;
|
|
rateTotal = 0;
|
|
rateHits = 0;
|
|
}
|
|
|
|
rateTotal++;
|
|
if (rate > (double) rateHits / rateTotal) {
|
|
rateHits++;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set the number of times profiling has been collected for this query
|
|
* point.
|
|
*/
|
|
public void setProfileCount(int profileCount) {
|
|
// int assignment is atomic
|
|
this.profileCount = profileCount;
|
|
}
|
|
|
|
/**
|
|
* Set the tuned query detail.
|
|
*/
|
|
public void setTunedDetail(OrmQueryDetail tunedDetail) {
|
|
// assignment is atomic
|
|
this.tunedDetail = tunedDetail;
|
|
this.lastTuneTime = Long.valueOf(System.currentTimeMillis());
|
|
}
|
|
|
|
/**
|
|
* Return true if the fetches are essentially the same.
|
|
*/
|
|
public boolean isSame(OrmQueryDetail newQueryDetail) {
|
|
if (tunedDetail == null) {
|
|
return false;
|
|
}
|
|
return tunedDetail.isAutoFetchEqual(newQueryDetail);
|
|
}
|
|
|
|
/**
|
|
* Tune the query by replacing its OrmQueryDetail with a tuned one.
|
|
*
|
|
* @return true if the query was tuned, otherwise false.
|
|
*/
|
|
public boolean autoFetchTune(SpiQuery<?> query) {
|
|
if (tunedDetail == null) {
|
|
return false;
|
|
}
|
|
|
|
boolean tuned = false;
|
|
//Note: tunedDetail is immutable by convention
|
|
if (query.isDetailEmpty()) {
|
|
tuned = true;
|
|
// tune by 'replacement'
|
|
query.setDetail(tunedDetail.copy());
|
|
} else {
|
|
// tune by 'addition'
|
|
tuned = query.tuneFetchProperties(tunedDetail);
|
|
}
|
|
if (tuned){
|
|
query.setAutoFetchTuned(true);
|
|
// a case for AtomicInteger but good enough for statistics
|
|
tunedCount++;
|
|
}
|
|
return tuned;
|
|
}
|
|
|
|
/**
|
|
* Return the time of the last tune.
|
|
*/
|
|
public Long getLastTuneTime() {
|
|
return lastTuneTime;
|
|
}
|
|
|
|
/**
|
|
* Return the number of queries tuned by this object.
|
|
*/
|
|
public int getTunedCount() {
|
|
return tunedCount;
|
|
}
|
|
|
|
/**
|
|
* Return the number of times profiling has been collected for this query
|
|
* point.
|
|
*/
|
|
public int getProfileCount() {
|
|
return profileCount;
|
|
}
|
|
|
|
public OrmQueryDetail getTunedDetail() {
|
|
return tunedDetail;
|
|
}
|
|
|
|
public ObjectGraphOrigin getOrigin() {
|
|
return origin;
|
|
}
|
|
|
|
public String getLogOutput(OrmQueryDetail newQueryDetail) {
|
|
|
|
boolean changed = newQueryDetail != null;
|
|
|
|
StringBuilder sb = new StringBuilder(150);
|
|
sb.append( changed ? "\"Changed\",":"\"New\",");
|
|
sb.append("\"").append(origin.getBeanType()).append("\",");
|
|
sb.append("\"").append(origin.getKey()).append("\",");
|
|
if (changed){
|
|
sb.append("\"to: ").append(newQueryDetail.toString()).append("\",");
|
|
sb.append("\"from: ").append(tunedDetail.toString()).append("\",");
|
|
} else {
|
|
sb.append("\"to: ").append(tunedDetail.toString()).append("\",");
|
|
sb.append("\"\",");
|
|
}
|
|
sb.append("\"").append(origin.getFirstStackElement()).append("\"");
|
|
|
|
return sb.toString();
|
|
}
|
|
|
|
public String toString() {
|
|
return origin.getBeanType()+" "+origin.getKey()+" " + tunedDetail;
|
|
}
|
|
|
|
}
|