package io.ebeaninternal.server.query;
import io.ebeaninternal.api.SpiDbQueryPlan;
import io.ebeaninternal.api.SpiQueryBindCapture;
import io.ebeaninternal.api.SpiQueryPlan;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
import java.util.concurrent.locks.ReentrantLock;
class CQueryBindCapture implements SpiQueryBindCapture {
private static final double multiplier = 1.3d;
private final ReentrantLock lock = new ReentrantLock();
private final CQueryPlanManager manager;
private final SpiQueryPlan queryPlan;
private BindCapture bindCapture;
private long queryTimeMicros;
private long thresholdMicros;
private long captureCount;
private long lastBindCapture;
CQueryBindCapture(CQueryPlanManager manager, SpiQueryPlan queryPlan, long thresholdMicros) {
this.manager = manager;
this.queryPlan = queryPlan;
this.thresholdMicros = thresholdMicros;
}
Return true if we should capture the bind values for this query.
/**
* Return true if we should capture the bind values for this query.
*/
@Override
public boolean collectFor(long timeMicros) {
return timeMicros > thresholdMicros && captureCount < 10;
}
@Override
public void setBind(BindCapture bindCapture, long queryTimeMicros, long startNanos) {
lock.lock();
try {
this.thresholdMicros = Math.round(queryTimeMicros * multiplier);
this.captureCount++;
this.bindCapture = bindCapture;
this.queryTimeMicros = queryTimeMicros;
lastBindCapture = System.currentTimeMillis();
manager.notifyBindCapture(this, startNanos);
} finally {
lock.unlock();
}
}
@Override
public void queryPlanInit(long thresholdMicros) {
// effective enable bind capture for this plan
this.thresholdMicros = thresholdMicros;
this.captureCount = 0;
}
Collect the query plan using already captured bind values.
/**
* Collect the query plan using already captured bind values.
*/
public boolean collectQueryPlan(CQueryPlanRequest request) {
if (bindCapture == null || request.getSince() < lastBindCapture) {
// no bind capture since the last capture
return false;
}
final BindCapture last = this.bindCapture;
SpiDbQueryPlan queryPlan = manager.collectPlan(request.getConnection(), this.queryPlan, last);
if (queryPlan != null) {
request.add(queryPlan.with(queryTimeMicros, captureCount));
// effectively turn off bind capture for this plan
thresholdMicros = Long.MAX_VALUE;
return true;
}
return false;
}
}