From 1d471fee92c3ff45d7cdfe582c0ccbc61748921a Mon Sep 17 00:00:00 2001
From: Rob Bygrave
Date: Wed, 14 Aug 2019 17:02:57 +1200
Subject: [PATCH] #1768 - Initial refactor extracting CallOrigin interface
(#1791)
---
src/main/java/io/ebean/bean/CallOrigin.java | 22 +++++
src/main/java/io/ebean/bean/CallStack.java | 81 +++++--------------
.../java/io/ebean/bean/ObjectGraphOrigin.java | 22 ++---
.../java/io/ebean/config/ServerConfig.java | 1 +
src/main/java/io/ebean/util/EncodeB64.java | 32 ++++++++
.../io/ebeaninternal/api/SpiEbeanServer.java | 4 +-
.../java/io/ebeaninternal/api/SpiQuery.java | 4 +-
.../service/AutoTuneDiffCollection.java | 2 +-
.../autotune/service/BaseQueryTuner.java | 12 +--
.../server/core/CallOriginFactory.java | 14 ++++
.../server/core/CallStackFactory.java | 14 ----
...ory.java => DefaultCallOriginFactory.java} | 9 ++-
.../server/core/DefaultServer.java | 16 ++--
.../server/core/DefaultSlowQueryListener.java | 2 +-
.../server/core/NoopCallOriginFactory.java | 17 ++++
.../server/core/NoopCallStackFactory.java | 16 ----
.../server/loadcontext/DLoadContext.java | 6 +-
.../server/querydefn/DefaultOrmQuery.java | 6 +-
.../ebeaninternal/api/TDSpiEbeanServer.java | 4 +-
.../query/autotune/TestAutoTuneProfiling.java | 4 +-
.../org/tests/unitinternal/TestEncodeB64.java | 29 +++++++
.../unitinternal/TestOriginIntEncoding.java | 30 -------
src/test/resources/ebean.properties | 1 +
23 files changed, 184 insertions(+), 164 deletions(-)
create mode 100644 src/main/java/io/ebean/bean/CallOrigin.java
create mode 100644 src/main/java/io/ebean/util/EncodeB64.java
create mode 100644 src/main/java/io/ebeaninternal/server/core/CallOriginFactory.java
delete mode 100644 src/main/java/io/ebeaninternal/server/core/CallStackFactory.java
rename src/main/java/io/ebeaninternal/server/core/{DefaultCallStackFactory.java => DefaultCallOriginFactory.java} (88%)
create mode 100644 src/main/java/io/ebeaninternal/server/core/NoopCallOriginFactory.java
delete mode 100644 src/main/java/io/ebeaninternal/server/core/NoopCallStackFactory.java
create mode 100644 src/test/java/org/tests/unitinternal/TestEncodeB64.java
delete mode 100644 src/test/java/org/tests/unitinternal/TestOriginIntEncoding.java
diff --git a/src/main/java/io/ebean/bean/CallOrigin.java b/src/main/java/io/ebean/bean/CallOrigin.java
new file mode 100644
index 000000000..4ef531944
--- /dev/null
+++ b/src/main/java/io/ebean/bean/CallOrigin.java
@@ -0,0 +1,22 @@
+package io.ebean.bean;
+
+/**
+ * A call origin for query execution profiling to collect graph use (for query tuning).
+ */
+public interface CallOrigin {
+
+ /**
+ * Return the top element. Typically the top stack element with class and line.
+ */
+ String getTopElement();
+
+ /**
+ * Return the full description of the call origin.
+ */
+ String getFullDescription();
+
+ /**
+ * Compute and return an origin key based on the query hash.
+ */
+ String getOriginKey(int queryHash);
+}
diff --git a/src/main/java/io/ebean/bean/CallStack.java b/src/main/java/io/ebean/bean/CallStack.java
index d9006a026..2d2a5ffe5 100644
--- a/src/main/java/io/ebean/bean/CallStack.java
+++ b/src/main/java/io/ebean/bean/CallStack.java
@@ -3,6 +3,8 @@ package io.ebean.bean;
import java.io.Serializable;
import java.util.Arrays;
+import static io.ebean.util.EncodeB64.enc;
+
/**
* Represent the call stack (stack trace elements).
*
@@ -17,15 +19,15 @@ import java.util.Arrays;
* Note the call stack is trimmed to remove the common ebean internal elements.
*
*/
-public final class CallStack implements Serializable {
+public final class CallStack implements Serializable, CallOrigin {
private static final long serialVersionUID = -8590644046907438579L;
+ private static final String NEWLINE = "\n";
+
private final String zeroHash;
private final String pathHash;
-
private final StackTraceElement[] callStack;
-
private final int hc;
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
@@ -37,12 +39,17 @@ public final class CallStack implements Serializable {
private int computeHashCode() {
int hc = 0;
- for (StackTraceElement aCallStack : callStack) {
- hc = 92821 * hc + aCallStack.hashCode();
+ for (StackTraceElement element : callStack) {
+ hc = 92821 * hc + element.hashCode();
}
return hc;
}
+ @Override
+ public String toString() {
+ return zeroHash + ":" + pathHash + ":" + callStack[0];
+ }
+
@Override
public int hashCode() {
return hc;
@@ -63,73 +70,29 @@ public final class CallStack implements Serializable {
/**
* Return the first element of the call stack.
*/
- public StackTraceElement getFirstStackTraceElement() {
- return callStack[0];
- }
-
- /**
- * Return the call stack.
- */
- public StackTraceElement[] getCallStack() {
- return callStack;
- }
-
- /**
- * Return the hash for the first stack element.
- */
- public String getZeroHash() {
- return zeroHash;
- }
-
- /**
- * Return the hash for the stack elements (excluding first stack element).
- */
- public String getPathHash() {
- return pathHash;
- }
-
@Override
- public String toString() {
- return zeroHash + ":" + pathHash + ":" + callStack[0];
+ public String getTopElement() {
+ return callStack[0].toString();
}
/**
* Return the call stack lines appended with the given newLine string.
*/
- public String description(String newLine) {
+ @Override
+ public String getFullDescription() {
StringBuilder sb = new StringBuilder(400);
- for (StackTraceElement aCallStack : callStack) {
- sb.append(aCallStack.toString()).append(newLine);
+ for (int i = 0; i < callStack.length; i++) {
+ if (i > 0) {
+ sb.append(NEWLINE);
+ }
+ sb.append(callStack[i].toString());
}
return sb.toString();
}
+ @Override
public String getOriginKey(int queryHash) {
return enc(queryHash) + "." + zeroHash + "." + pathHash;
}
- private static final int radix = 1 << 6;
- private static final int mask = radix - 1;
-
- /**
- * Convert the integer to unsigned base 64.
- */
- public static String enc(int i) {
- char[] buf = new char[32];
- int charPos = 32;
- do {
- buf[--charPos] = intToBase64[i & mask];
- i >>>= 6;
- } while (i != 0);
-
- return new String(buf, charPos, (32 - charPos));
- }
-
- private static final char intToBase64[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
- };
}
diff --git a/src/main/java/io/ebean/bean/ObjectGraphOrigin.java b/src/main/java/io/ebean/bean/ObjectGraphOrigin.java
index 5f32f44ef..07d636a01 100644
--- a/src/main/java/io/ebean/bean/ObjectGraphOrigin.java
+++ b/src/main/java/io/ebean/bean/ObjectGraphOrigin.java
@@ -16,7 +16,7 @@ public final class ObjectGraphOrigin implements Serializable {
private static final long serialVersionUID = 410937765287968708L;
- private final CallStack callStack;
+ private final CallOrigin callOrigin;
private final String beanType;
@@ -24,11 +24,11 @@ public final class ObjectGraphOrigin implements Serializable {
private final String key;
- public ObjectGraphOrigin(int queryHash, CallStack callStack, String beanType) {
- this.callStack = callStack;
+ public ObjectGraphOrigin(int queryHash, CallOrigin callOrigin, String beanType) {
+ this.callOrigin = callOrigin;
this.beanType = beanType;
this.queryHash = queryHash;
- this.key = callStack.getOriginKey(queryHash);
+ this.key = callOrigin.getOriginKey(queryHash);
}
/**
@@ -49,22 +49,22 @@ public final class ObjectGraphOrigin implements Serializable {
/**
* The call stack involved.
*/
- public CallStack getCallStack() {
- return callStack;
+ public CallOrigin getCallOrigin() {
+ return callOrigin;
}
- public String getFirstStackElement() {
- return callStack.getFirstStackTraceElement().toString();
+ public String getTopElement() {
+ return callOrigin.getTopElement();
}
@Override
public String toString() {
- return "key[" + key + "] type[" + beanType + "] " + callStack.getFirstStackTraceElement() + " ";
+ return "key[" + key + "] type[" + beanType + "] " + callOrigin.getTopElement();
}
@Override
public int hashCode() {
- int hc = 92821 * callStack.hashCode();
+ int hc = 92821 * callOrigin.hashCode();
hc = 92821 * hc + beanType.hashCode();
hc = 92821 * hc + queryHash;
return hc;
@@ -82,6 +82,6 @@ public final class ObjectGraphOrigin implements Serializable {
ObjectGraphOrigin e = (ObjectGraphOrigin) obj;
return e.queryHash == queryHash
&& e.beanType.equals(beanType)
- && e.callStack.equals(callStack);
+ && e.callOrigin.equals(callOrigin);
}
}
diff --git a/src/main/java/io/ebean/config/ServerConfig.java b/src/main/java/io/ebean/config/ServerConfig.java
index 76cb0654c..3603fa9d2 100644
--- a/src/main/java/io/ebean/config/ServerConfig.java
+++ b/src/main/java/io/ebean/config/ServerConfig.java
@@ -2929,6 +2929,7 @@ public class ServerConfig {
}
loadDocStoreSettings(p);
+ maxCallStack = p.getInt("maxCallStack", maxCallStack);
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
diff --git a/src/main/java/io/ebean/util/EncodeB64.java b/src/main/java/io/ebean/util/EncodeB64.java
new file mode 100644
index 000000000..9eedf9c02
--- /dev/null
+++ b/src/main/java/io/ebean/util/EncodeB64.java
@@ -0,0 +1,32 @@
+package io.ebean.util;
+
+/**
+ * Integer to base64 encoder.
+ */
+public final class EncodeB64 {
+
+ private static final int radix = 1 << 6;
+ private static final int mask = radix - 1;
+
+ /**
+ * Convert the integer to unsigned base 64.
+ */
+ public static String enc(int i) {
+ char[] buf = new char[32];
+ int charPos = 32;
+ do {
+ buf[--charPos] = intToBase64[i & mask];
+ i >>>= 6;
+ } while (i != 0);
+
+ return new String(buf, charPos, (32 - charPos));
+ }
+
+ private static final char intToBase64[] = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
+ };
+}
diff --git a/src/main/java/io/ebeaninternal/api/SpiEbeanServer.java b/src/main/java/io/ebeaninternal/api/SpiEbeanServer.java
index b8e4e9b7c..e594395d2 100644
--- a/src/main/java/io/ebeaninternal/api/SpiEbeanServer.java
+++ b/src/main/java/io/ebeaninternal/api/SpiEbeanServer.java
@@ -11,7 +11,7 @@ import io.ebean.Transaction;
import io.ebean.TxScope;
import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.BeanLoader;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.ServerConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
@@ -81,7 +81,7 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanLoader,
* graph costing.
*
*/
- CallStack createCallStack();
+ CallOrigin createCallOrigin();
/**
* Return the PersistenceContextScope to use defined at query or server level.
diff --git a/src/main/java/io/ebeaninternal/api/SpiQuery.java b/src/main/java/io/ebeaninternal/api/SpiQuery.java
index 112c0c7b8..7f3f5596f 100644
--- a/src/main/java/io/ebeaninternal/api/SpiQuery.java
+++ b/src/main/java/io/ebeaninternal/api/SpiQuery.java
@@ -7,7 +7,7 @@ import io.ebean.OrderBy;
import io.ebean.PersistenceContextScope;
import io.ebean.ProfileLocation;
import io.ebean.Query;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.PersistenceContext;
import io.ebean.event.readaudit.ReadEvent;
@@ -558,7 +558,7 @@ public interface SpiQuery extends Query, TxnProfileEventCodes {
* because the queryPlanHash is used to identify the query point.
*
*/
- ObjectGraphNode setOrigin(CallStack callStack);
+ ObjectGraphNode setOrigin(CallOrigin callOrigin);
/**
* Set the profile point of the bean or collection that is lazy loading.
diff --git a/src/main/java/io/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java b/src/main/java/io/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java
index 4f8213388..2d3d3e04c 100644
--- a/src/main/java/io/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java
+++ b/src/main/java/io/ebeaninternal/server/autotune/service/AutoTuneDiffCollection.java
@@ -149,7 +149,7 @@ public class AutoTuneDiffCollection {
origin.setKey(point.getKey());
origin.setBeanType(point.getBeanType());
origin.setDetail(entry.getDetail().toString());
- origin.setCallStack(point.getCallStack().description("\n"));
+ origin.setCallStack(point.getCallOrigin().getFullDescription());
origin.setOriginal(query);
if (updateTuning) {
diff --git a/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java b/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java
index 8219b179c..5a9a99130 100644
--- a/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java
+++ b/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.autotune.service;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.AutoTuneConfig;
import io.ebean.config.AutoTuneMode;
@@ -97,7 +97,7 @@ public class BaseQueryTuner {
if (!useTuning(query)) {
if (profiling) {
- profiling(query, server.createCallStack());
+ profiling(query, server.createCallOrigin());
}
return false;
}
@@ -110,8 +110,8 @@ public class BaseQueryTuner {
}
// create a query point to identify the query
- CallStack stack = server.createCallStack();
- ObjectGraphNode origin = query.setOrigin(stack);
+ CallOrigin callOrigin = server.createCallOrigin();
+ ObjectGraphNode origin = query.setOrigin(callOrigin);
if (profiling) {
if (profilingListener.isProfileRequest(origin, query)) {
@@ -154,10 +154,10 @@ public class BaseQueryTuner {
}
}
- private void profiling(SpiQuery> query, CallStack stack) {
+ private void profiling(SpiQuery> query, CallOrigin call) {
// create a query point to identify the query
- ObjectGraphNode origin = query.setOrigin(stack);
+ ObjectGraphNode origin = query.setOrigin(call);
if (profilingListener.isProfileRequest(origin, query)) {
// collect more profiling based on profiling rate etc
query.setProfilingListener(profilingListener);
diff --git a/src/main/java/io/ebeaninternal/server/core/CallOriginFactory.java b/src/main/java/io/ebeaninternal/server/core/CallOriginFactory.java
new file mode 100644
index 000000000..5de09a508
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/core/CallOriginFactory.java
@@ -0,0 +1,14 @@
+package io.ebeaninternal.server.core;
+
+import io.ebean.bean.CallOrigin;
+
+/**
+ * Creates CallOrigin based on the stack trace.
+ */
+public interface CallOriginFactory {
+
+ /**
+ * Create and return the CallStack given the stack trace elements.
+ */
+ CallOrigin createCallOrigin();
+}
diff --git a/src/main/java/io/ebeaninternal/server/core/CallStackFactory.java b/src/main/java/io/ebeaninternal/server/core/CallStackFactory.java
deleted file mode 100644
index b61c40370..000000000
--- a/src/main/java/io/ebeaninternal/server/core/CallStackFactory.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package io.ebeaninternal.server.core;
-
-import io.ebean.bean.CallStack;
-
-/**
- * Creates CallStack based on the stack trace.
- */
-public interface CallStackFactory {
-
- /**
- * Create and return the CallStack given the stack trace elements.
- */
- CallStack createCallStack();
-}
diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultCallStackFactory.java b/src/main/java/io/ebeaninternal/server/core/DefaultCallOriginFactory.java
similarity index 88%
rename from src/main/java/io/ebeaninternal/server/core/DefaultCallStackFactory.java
rename to src/main/java/io/ebeaninternal/server/core/DefaultCallOriginFactory.java
index 169faa93d..249f4dbdb 100644
--- a/src/main/java/io/ebeaninternal/server/core/DefaultCallStackFactory.java
+++ b/src/main/java/io/ebeaninternal/server/core/DefaultCallOriginFactory.java
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.core;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.CallStack;
import java.util.Arrays;
@@ -7,7 +8,7 @@ import java.util.Arrays;
/**
* Default CallStackFactory where the Hash function for StackTraceElement includes the line number.
*/
-public class DefaultCallStackFactory implements CallStackFactory {
+public class DefaultCallOriginFactory implements CallOriginFactory {
private static final int IGNORE_LEADING_ELEMENTS = 5;
@@ -15,12 +16,12 @@ public class DefaultCallStackFactory implements CallStackFactory {
private final int maxCallStack;
- DefaultCallStackFactory(int maxCallStack) {
+ DefaultCallOriginFactory(int maxCallStack) {
this.maxCallStack = maxCallStack;
}
@Override
- public CallStack createCallStack() {
+ public CallOrigin createCallOrigin() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
// ignore the first 6 as they are always avaje stack elements
@@ -58,7 +59,7 @@ public class DefaultCallStackFactory implements CallStackFactory {
return element.getMethodName().startsWith("_ebean_");
}
- private CallStack createCallStack(StackTraceElement[] finalTrace) {
+ private CallOrigin createCallStack(StackTraceElement[] finalTrace) {
return new CallStack(finalTrace, finalTrace[0].hashCode(), pathHash(finalTrace));
}
diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
index 708a379d7..7f141146a 100644
--- a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
+++ b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java
@@ -35,7 +35,7 @@ import io.ebean.ValuePair;
import io.ebean.Version;
import io.ebean.annotation.TxIsolation;
import io.ebean.bean.BeanCollection;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.ObjectGraphNode;
@@ -164,7 +164,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
*/
private final ClockService clockService;
- private final CallStackFactory callStackFactory;
+ private final CallOriginFactory callStackFactory;
/**
* Handles the save, delete, updateSql CallableSql.
@@ -312,12 +312,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
/**
* Create the CallStackFactory depending if AutoTune is being used.
*/
- private CallStackFactory initCallStackFactory(ServerConfig serverConfig) {
+ private CallOriginFactory initCallStackFactory(ServerConfig serverConfig) {
if (!serverConfig.getAutoTuneConfig().isActive()) {
// use a common CallStack for performance as we don't care with no AutoTune
- return new NoopCallStackFactory();
+ return new NoopCallOriginFactory();
}
- return new DefaultCallStackFactory(serverConfig.getMaxCallStack());
+ return new DefaultCallOriginFactory(serverConfig.getMaxCallStack());
}
private void configureServerPlugins() {
@@ -1135,7 +1135,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
// if determine cost and no origin for AutoTune
if (query.getParentNode() == null) {
- query.setOrigin(createCallStack());
+ query.setOrigin(createCallOrigin());
}
return new OrmQueryRequest<>(this, queryEngine, query, (SpiTransaction) t);
@@ -2309,8 +2309,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
*
*/
@Override
- public CallStack createCallStack() {
- return callStackFactory.createCallStack();
+ public CallOrigin createCallOrigin() {
+ return callStackFactory.createCallOrigin();
}
@Override
diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultSlowQueryListener.java b/src/main/java/io/ebeaninternal/server/core/DefaultSlowQueryListener.java
index e6e02833e..b271a513e 100644
--- a/src/main/java/io/ebeaninternal/server/core/DefaultSlowQueryListener.java
+++ b/src/main/java/io/ebeaninternal/server/core/DefaultSlowQueryListener.java
@@ -19,7 +19,7 @@ class DefaultSlowQueryListener implements SlowQueryListener {
String firstStack = "";
ObjectGraphNode node = event.getOriginNode();
if (node != null) {
- firstStack = node.getOriginQueryPoint().getFirstStackElement();
+ firstStack = node.getOriginQueryPoint().getTopElement();
}
log.warn("Slow query warning - millis:{} rows:{} caller[{}] sql[{}]", event.getTimeMillis(), event.getRowCount(), firstStack, event.getSql());
}
diff --git a/src/main/java/io/ebeaninternal/server/core/NoopCallOriginFactory.java b/src/main/java/io/ebeaninternal/server/core/NoopCallOriginFactory.java
new file mode 100644
index 000000000..314b32c68
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/server/core/NoopCallOriginFactory.java
@@ -0,0 +1,17 @@
+package io.ebeaninternal.server.core;
+
+import io.ebean.bean.CallOrigin;
+import io.ebean.bean.CallStack;
+
+/**
+ * A CallOriginFactory we can use when we don't use AutoTune.
+ */
+class NoopCallOriginFactory implements CallOriginFactory {
+
+ private final CallOrigin COMMON = new CallStack(Thread.currentThread().getStackTrace(), 0, 0);
+
+ @Override
+ public CallOrigin createCallOrigin() {
+ return COMMON;
+ }
+}
diff --git a/src/main/java/io/ebeaninternal/server/core/NoopCallStackFactory.java b/src/main/java/io/ebeaninternal/server/core/NoopCallStackFactory.java
deleted file mode 100644
index 8e04cd414..000000000
--- a/src/main/java/io/ebeaninternal/server/core/NoopCallStackFactory.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.ebeaninternal.server.core;
-
-import io.ebean.bean.CallStack;
-
-/**
- * A CallStackFactory we can use when we don't use AutoTune.
- */
-class NoopCallStackFactory implements CallStackFactory {
-
- private final CallStack COMMON = new CallStack(Thread.currentThread().getStackTrace(), 0, 0);
-
- @Override
- public CallStack createCallStack() {
- return COMMON;
- }
-}
diff --git a/src/main/java/io/ebeaninternal/server/loadcontext/DLoadContext.java b/src/main/java/io/ebeaninternal/server/loadcontext/DLoadContext.java
index 1f2e2e297..bac4528e8 100644
--- a/src/main/java/io/ebeaninternal/server/loadcontext/DLoadContext.java
+++ b/src/main/java/io/ebeaninternal/server/loadcontext/DLoadContext.java
@@ -3,7 +3,7 @@ package io.ebeaninternal.server.loadcontext;
import io.ebean.CacheMode;
import io.ebean.ProfileLocation;
import io.ebean.bean.BeanCollection;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.ObjectGraphOrigin;
@@ -94,8 +94,8 @@ public class DLoadContext implements LoadContext {
}
private ObjectGraphOrigin initOrigin() {
- CallStack callStack = ebeanServer.createCallStack();
- return new ObjectGraphOrigin(0, callStack, rootDescriptor.getFullName());
+ CallOrigin callOrigin = ebeanServer.createCallOrigin();
+ return new ObjectGraphOrigin(0, callOrigin, rootDescriptor.getFullName());
}
public DLoadContext(OrmQueryRequest> request, SpiQuerySecondary secondaryQueries) {
diff --git a/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
index a63e9380b..b03596175 100644
--- a/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
+++ b/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
@@ -24,7 +24,7 @@ import io.ebean.RawSql;
import io.ebean.Transaction;
import io.ebean.UpdateQuery;
import io.ebean.Version;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.ObjectGraphOrigin;
import io.ebean.bean.PersistenceContext;
@@ -1073,10 +1073,10 @@ public class DefaultOrmQuery implements SpiQuery {
}
@Override
- public ObjectGraphNode setOrigin(CallStack callStack) {
+ public ObjectGraphNode setOrigin(CallOrigin callOrigin) {
// create a 'origin' which links this query to the profiling information
- ObjectGraphOrigin o = new ObjectGraphOrigin(calculateOriginQueryHash(), callStack, beanType.getName());
+ ObjectGraphOrigin o = new ObjectGraphOrigin(calculateOriginQueryHash(), callOrigin, beanType.getName());
parentNode = new ObjectGraphNode(o, null);
return parentNode;
}
diff --git a/src/test/java/io/ebeaninternal/api/TDSpiEbeanServer.java b/src/test/java/io/ebeaninternal/api/TDSpiEbeanServer.java
index e52dda337..5da3fdabf 100644
--- a/src/test/java/io/ebeaninternal/api/TDSpiEbeanServer.java
+++ b/src/test/java/io/ebeaninternal/api/TDSpiEbeanServer.java
@@ -32,7 +32,7 @@ import io.ebean.ValuePair;
import io.ebean.Version;
import io.ebean.annotation.TxIsolation;
import io.ebean.bean.BeanCollection;
-import io.ebean.bean.CallStack;
+import io.ebean.bean.CallOrigin;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.cache.ServerCacheManager;
@@ -168,7 +168,7 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
}
@Override
- public CallStack createCallStack() {
+ public CallOrigin createCallOrigin() {
return null;
}
diff --git a/src/test/java/org/tests/query/autotune/TestAutoTuneProfiling.java b/src/test/java/org/tests/query/autotune/TestAutoTuneProfiling.java
index 6f1a020fd..e12491f64 100644
--- a/src/test/java/org/tests/query/autotune/TestAutoTuneProfiling.java
+++ b/src/test/java/org/tests/query/autotune/TestAutoTuneProfiling.java
@@ -21,7 +21,7 @@ public class TestAutoTuneProfiling extends BaseTestCase {
ResetBasicData.reset();
- for (int i = 0; i < 1; i++) {
+ for (int i = 0; i < 10; i++) {
execute();
}
collectUsage();
@@ -35,7 +35,7 @@ public class TestAutoTuneProfiling extends BaseTestCase {
sortOfBusy();
- for (int i = 0; i < 1; i++) {
+ for (int i = 0; i < 10; i++) {
execute();
}
}
diff --git a/src/test/java/org/tests/unitinternal/TestEncodeB64.java b/src/test/java/org/tests/unitinternal/TestEncodeB64.java
new file mode 100644
index 000000000..95124fcad
--- /dev/null
+++ b/src/test/java/org/tests/unitinternal/TestEncodeB64.java
@@ -0,0 +1,29 @@
+package org.tests.unitinternal;
+
+import org.junit.Test;
+
+import static io.ebean.util.EncodeB64.enc;
+import static org.junit.Assert.assertEquals;
+
+public class TestEncodeB64 {
+
+ @Test
+ public void test() {
+
+ assertEquals("A", enc(0));
+ assertEquals("B", enc(1));
+ assertEquals("Z", enc(25));
+ assertEquals("a", enc(26));
+ assertEquals("z", enc(51));
+ assertEquals("0", enc(52));
+ assertEquals("9", enc(61));
+ assertEquals("-", enc(62));
+ assertEquals("_", enc(63));
+ assertEquals("BA", enc(64));
+ assertEquals("Bk", enc(100));
+ assertEquals("B9", enc(125));
+ assertEquals("B-", enc(126));
+ assertEquals("B_", enc(127));
+ assertEquals("CA", enc(128));
+ }
+}
diff --git a/src/test/java/org/tests/unitinternal/TestOriginIntEncoding.java b/src/test/java/org/tests/unitinternal/TestOriginIntEncoding.java
deleted file mode 100644
index 78a6267be..000000000
--- a/src/test/java/org/tests/unitinternal/TestOriginIntEncoding.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.tests.unitinternal;
-
-import io.ebean.BaseTestCase;
-import io.ebean.bean.CallStack;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestOriginIntEncoding extends BaseTestCase {
-
- @Test
- public void test() {
-
- Assert.assertEquals("A", CallStack.enc(0));
- Assert.assertEquals("B", CallStack.enc(1));
- Assert.assertEquals("Z", CallStack.enc(25));
- Assert.assertEquals("a", CallStack.enc(26));
- Assert.assertEquals("z", CallStack.enc(51));
- Assert.assertEquals("0", CallStack.enc(52));
- Assert.assertEquals("9", CallStack.enc(61));
- Assert.assertEquals("-", CallStack.enc(62));
- Assert.assertEquals("_", CallStack.enc(63));
- Assert.assertEquals("BA", CallStack.enc(64));
- Assert.assertEquals("Bk", CallStack.enc(100));
- Assert.assertEquals("B9", CallStack.enc(125));
- Assert.assertEquals("B-", CallStack.enc(126));
- Assert.assertEquals("B_", CallStack.enc(127));
- Assert.assertEquals("CA", CallStack.enc(128));
-
- }
-}
diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties
index ccca26091..e1c4edbc6 100644
--- a/src/test/resources/ebean.properties
+++ b/src/test/resources/ebean.properties
@@ -12,6 +12,7 @@
ebean.encryptKeyManager=org.tests.basic.encrypt.BasicEncyptKeyManager
#ebean.disableL2Cache=true
+#ebean.maxCallStack=1
#ebean.autoTune.queryTuning=true
#ebean.autoTune.mode=DEFAULT_ON
#ebean.autoTune.profiling=true