You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2010/08/12 04:40:23 UTC
svn commit: r984633 - in /openjpa/trunk:
openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/
openjpa-integration/jmx/src/test/resources/META-INF/
openjpa-kernel/src/main/java/org/apache/openjpa/datacache/
openjpa-kernel/src/main/j...
Author: jrbauer
Date: Thu Aug 12 02:40:23 2010
New Revision: 984633
URL: http://svn.apache.org/viewvc?rev=984633&view=rev
Log:
OPENJPA-1739 Added basic stats tracking to query result cache. Updates to JMX provider. Added tests to jmx module for query cache and prepared SQL cache instruments.
Modified:
openjpa/trunk/openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/TestJMXPlatformMBeans.java
openjpa/trunk/openjpa-integration/jmx/src/test/resources/META-INF/persistence.xml
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.java
openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/instrumentation/Instrument.java
Modified: openjpa/trunk/openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/TestJMXPlatformMBeans.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/TestJMXPlatformMBeans.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/TestJMXPlatformMBeans.java (original)
+++ openjpa/trunk/openjpa-integration/jmx/src/test/java/org/apache/openjpa/integration/jmx/TestJMXPlatformMBeans.java Thu Aug 12 02:40:23 2010
@@ -19,14 +19,22 @@
package org.apache.openjpa.integration.jmx;
import java.lang.management.ManagementFactory;
+import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import javax.persistence.Query;
import org.apache.openjpa.instrumentation.DataCacheInstrument;
import org.apache.openjpa.instrumentation.InstrumentationManager;
+import org.apache.openjpa.instrumentation.PreparedQueryCacheInstrument;
+import org.apache.openjpa.instrumentation.QueryCacheInstrument;
import org.apache.openjpa.instrumentation.jmx.JMXProvider;
import org.apache.openjpa.lib.instrumentation.Instrument;
import org.apache.openjpa.lib.instrumentation.InstrumentationProvider;
@@ -35,11 +43,10 @@ import org.apache.openjpa.persistence.Op
import org.apache.openjpa.persistence.test.AbstractPersistenceTestCase;
public class TestJMXPlatformMBeans extends AbstractPersistenceTestCase {
+
/**
- * Verifies the data cache metrics are available through simple instrumentation.
+ * Verifies data cache metrics are available through simple instrumentation.
*/
-
- @SuppressWarnings("deprecation")
public void testDataCacheInstrument() {
OpenJPAEntityManagerFactorySPI oemf = createNamedEMF("openjpa-integration-jmx");
@@ -78,30 +85,167 @@ public class TestJMXPlatformMBeans exten
// Thread out to do out-of-band MBean-based validation. This could
// have been done on the same thread, but threading out makes for a
// more realistic test.
- Thread thr = new Thread(new DCMBeanThread());
- thr.start();
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ Future<Boolean> result = executor.submit(new DCMBeanCallable());
try {
- thr.join(60000); // Wait for 1 minute for the MBean thread to return.
- if (thr.isAlive()) {
- // MBean did not return within a minute, interrupt it.
- thr.interrupt();
- Thread.sleep(5000);
- if (thr.isAlive()) {
- // Attempt to hard kill the thread to prevent the test from hanging
- thr.stop();
- }
- fail("DataCache MBean verification thread failed.");
- }
+ assertTrue(result.get());
} catch (Throwable t) {
- fail("Caught unexpected throwable: " + t);
+ fail("DataCache verification failed: " + t);
}
closeEMF(oemf);
}
- public class DCMBeanThread implements Runnable {
+ /**
+ * Verifies query cache metrics are available through simple instrumentation.
+ */
+ public void testQueryCacheInstrument() {
+ OpenJPAEntityManagerFactorySPI oemf = createNamedEMF("openjpa-integration-jmx");
+
+ // Verify an EMF was created with the supplied instrumentation
+ assertNotNull(oemf);
- public void run() {
+ // Verify an instrumentation manager is available
+ InstrumentationManager mgr = oemf.getConfiguration().getInstrumentationManagerInstance();
+ assertNotNull(mgr);
+
+ // Get the in-band data cache instrument
+ Set<InstrumentationProvider> providers = mgr.getProviders();
+ assertNotNull(providers);
+ assertEquals(1, providers.size());
+ InstrumentationProvider provider = providers.iterator().next();
+ assertEquals(provider.getClass(), JMXProvider.class);
+
+ Instrument inst = provider.getInstrumentByName("QueryCache");
+ assertNotNull(inst);
+ assertTrue(inst instanceof QueryCacheInstrument);
+ QueryCacheInstrument qci = (QueryCacheInstrument)inst;
+
+ assertEquals(0,qci.getExecutionCount());
+ assertEquals(0,qci.getTotalExecutionCount());
+ assertEquals(0,qci.getHitCount());
+ assertEquals(0,qci.getTotalHitCount());
+
+ OpenJPAEntityManagerSPI oem = oemf.createEntityManager();
+
+ CachedEntity ce = new CachedEntity();
+ int id = new Random().nextInt();
+ ce.setId(id);
+ CachedEntity ce2 = new CachedEntity();
+ id = new Random().nextInt();
+ ce2.setId(id);
+
+ oem.getTransaction().begin();
+ oem.persist(ce);
+ oem.persist(ce2);
+ oem.getTransaction().commit();
+
+ Query q = oem.createQuery("SELECT ce FROM CachedEntity ce");
+
+ List<?> result = q.getResultList();
+ assertNotNull(result);
+ assertTrue(result.size() > 1);
+ oem.clear();
+
+ result = q.getResultList();
+
+ assertTrue(qci.getExecutionCount() > 0);
+ assertTrue(qci.getTotalExecutionCount() > 0);
+ assertTrue(qci.getHitCount() > 0);
+ assertTrue(qci.getTotalHitCount() > 0);
+
+ // Thread out to do out-of-band MBean-based validation. This could
+ // have been done on the same thread, but threading out makes for a
+ // more realistic test.
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ Future<Boolean> execResult = executor.submit(new QueryCachesMBeanCallable(
+ QueryCachesMBeanCallable.QC_OBJNAME,
+ QueryCachesMBeanCallable.QC_QM));
+ try {
+ assertTrue(execResult.get());
+ } catch (Throwable t) {
+ fail("QueryCache verification failed: " + t);
+ }
+ closeEMF(oemf);
+ }
+
+ /**
+ * Verifies prepared query cache metrics are available through simple instrumentation.
+ */
+ public void testPreparedQueryCacheInstrument() {
+ OpenJPAEntityManagerFactorySPI oemf = createNamedEMF("openjpa-integration-jmx-qsc");
+
+ // Verify an EMF was created with the supplied instrumentation
+ assertNotNull(oemf);
+
+ // Verify an instrumentation manager is available
+ InstrumentationManager mgr = oemf.getConfiguration().getInstrumentationManagerInstance();
+ assertNotNull(mgr);
+
+ // Get the in-band data cache instrument
+ Set<InstrumentationProvider> providers = mgr.getProviders();
+ assertNotNull(providers);
+ assertEquals(1, providers.size());
+ InstrumentationProvider provider = providers.iterator().next();
+ assertEquals(provider.getClass(), JMXProvider.class);
+
+ Instrument inst = provider.getInstrumentByName("QuerySQLCache");
+ assertNotNull(inst);
+ assertTrue(inst instanceof PreparedQueryCacheInstrument);
+ PreparedQueryCacheInstrument qci = (PreparedQueryCacheInstrument)inst;
+
+ assertEquals(0,qci.getExecutionCount());
+ assertEquals(0,qci.getTotalExecutionCount());
+ assertEquals(0,qci.getHitCount());
+ assertEquals(0,qci.getTotalHitCount());
+
+ OpenJPAEntityManagerSPI oem = oemf.createEntityManager();
+
+ CachedEntity ce = new CachedEntity();
+ int id = new Random().nextInt();
+ ce.setId(id);
+ CachedEntity ce2 = new CachedEntity();
+ id = new Random().nextInt();
+ ce2.setId(id);
+
+ oem.getTransaction().begin();
+ oem.persist(ce);
+ oem.persist(ce2);
+ oem.getTransaction().commit();
+
+ Query q = oem.createQuery("SELECT ce FROM CachedEntity ce");
+
+ List<?> result = q.getResultList();
+ assertNotNull(result);
+ assertTrue(result.size() > 1);
+ oem.clear();
+
+ result = q.getResultList();
+
+ assertTrue(qci.getExecutionCount() > 0);
+ assertTrue(qci.getTotalExecutionCount() > 0);
+ assertTrue(qci.getHitCount() > 0);
+ assertTrue(qci.getTotalHitCount() > 0);
+
+ // Thread out to do out-of-band MBean-based validation. This could
+ // have been done on the same thread, but threading out makes for a
+ // more realistic test.
+ ExecutorService executor = Executors.newFixedThreadPool(1);
+ Future<Boolean> execResult = executor.submit(new QueryCachesMBeanCallable(
+ QueryCachesMBeanCallable.QSC_OBJNAME,
+ QueryCachesMBeanCallable.QSC_QM));
+ try {
+ assertTrue(execResult.get());
+ } catch (Throwable t) {
+ fail("QueryCache verification failed: " + t);
+ }
+
+ closeEMF(oemf);
+ }
+
+ public class DCMBeanCallable implements Callable<Boolean> {
+
+ public Boolean call() {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
assertNotNull(mbs);
ObjectName objname = null;
@@ -144,7 +288,88 @@ public class TestJMXPlatformMBeans exten
assertEquals(0, clsWriteCount);
} catch (Exception e) {
fail("Unexpected exception: " + e);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public class QueryCachesMBeanCallable implements Callable<Boolean> {
+
+ public static final String QC_OBJNAME = "org.apache.openjpa:type=QueryCache,cfgid=openjpa-integration-jmx,*";
+ public static final String QSC_OBJNAME = "org.apache.openjpa:type=QuerySQLCache,cfgid=openjpa-integration-jmx-qsc,*";
+ public static final String QC_QM = "queryKeys";
+ public static final String QSC_QM = "queries";
+
+ private String _objNameStr;
+ private String _queryMethod;
+
+ public QueryCachesMBeanCallable(String objName, String queryMethod) {
+ setObjName(objName);
+ setQueryMethod(queryMethod);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Boolean call() {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ assertNotNull(mbs);
+ ObjectName objname = null;
+ try {
+ // Query for the QueryCache bean
+ objname = new ObjectName(getObjName());
+ Set<ObjectName> ons = mbs.queryNames(objname, null);
+ assertEquals(1, ons.size());
+ ObjectName on = ons.iterator().next();
+ // Assert query cache attributes can be accessed and are being updated through the MBean
+ long hitCount = (Long)mbs.getAttribute(on, "HitCount");
+ long execCount = (Long)mbs.getAttribute(on, "ExecutionCount");
+ assertTrue(hitCount > 0);
+ assertTrue(execCount > 0);
+ // Assert data cache MBean methods can be invoked
+
+ Set<String> keys = (Set<String>)mbs.invoke(on, getQueryMethod(), null, null);
+ assertNotNull(keys);
+ assertTrue(keys.size() > 0);
+ String[] sigs = new String[] { "java.lang.String" };
+ for (String key : keys) {
+ Object[] parms = new Object[] { key };
+ long queryHitCount = (Long)mbs.invoke(on, "getHitCount", parms, sigs);
+ long queryReadCount = (Long)mbs.invoke(on, "getExecutionCount", parms, sigs);
+ assertTrue(queryHitCount > 0);
+ assertTrue(queryReadCount > 0);
+ }
+ // Invoke the reset method and recollect stats
+ mbs.invoke(on, "reset", null, null);
+ hitCount = (Long)mbs.getAttribute(on, "HitCount");
+ execCount = (Long)mbs.getAttribute(on, "ExecutionCount");
+ assertEquals(0, hitCount);
+ assertEquals(0, execCount);
+
+ keys = (Set<String>)mbs.invoke(on, getQueryMethod(), null, null);
+ assertNotNull(keys);
+ assertEquals(0, keys.size());
+ } catch (Exception e) {
+ fail("Unexpected exception: " + e);
+ return false;
}
+ return true;
+ }
+
+ public void setObjName(String objNameStr) {
+ this._objNameStr = objNameStr;
+ }
+
+ public String getObjName() {
+ return _objNameStr;
+ }
+
+ public void setQueryMethod(String _queryMethod) {
+ this._queryMethod = _queryMethod;
+ }
+
+ public String getQueryMethod() {
+ return _queryMethod;
}
}
+
}
\ No newline at end of file
Modified: openjpa/trunk/openjpa-integration/jmx/src/test/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-integration/jmx/src/test/resources/META-INF/persistence.xml?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-integration/jmx/src/test/resources/META-INF/persistence.xml (original)
+++ openjpa/trunk/openjpa-integration/jmx/src/test/resources/META-INF/persistence.xml Thu Aug 12 02:40:23 2010
@@ -24,11 +24,23 @@
<description>PU for JMX Platform MBean Testing</description>
<class>org.apache.openjpa.integration.jmx.CachedEntity</class>
<properties>
- <property name="openjpa.Instrumentation" value="jmx(Instrument=DataCache)"/>
+ <property name="openjpa.Instrumentation" value="jmx(Instrument='DataCache,QueryCache')"/>
<property name="openjpa.DataCache" value="true(EnableStatistics=true)"/>
+ <property name="openjpa.QueryCache" value="true(EnableStatistics=true)"/>
<property name="openjpa.RemoteCommitProvider" value="sjvm"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
</properties>
</persistence-unit>
+
+ <persistence-unit name="openjpa-integration-jmx-qsc">
+ <description>PU for JMX Platform MBean Testing with PreparedQueryCache/QuerySQLCache</description>
+ <class>org.apache.openjpa.integration.jmx.CachedEntity</class>
+ <properties>
+ <property name="openjpa.Instrumentation" value="jmx(Instrument=QuerySQLCache)"/>
+ <property name="openjpa.jdbc.QuerySQLCache" value="true(EnableStatistics=true)"/>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
+ <property name="openjpa.DynamicEnhancementAgent" value="false"/>
+ </properties>
+ </persistence-unit>
</persistence>
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/AbstractQueryCache.java Thu Aug 12 02:40:23 2010
@@ -18,9 +18,11 @@
*/
package org.apache.openjpa.datacache;
+import java.io.PrintStream;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -32,6 +34,7 @@ import java.util.concurrent.ConcurrentHa
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.event.RemoteCommitEvent;
import org.apache.openjpa.event.RemoteCommitListener;
+import org.apache.openjpa.kernel.QueryStatistics;
import org.apache.openjpa.lib.conf.Configurable;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.log.Log;
@@ -39,6 +42,7 @@ import org.apache.openjpa.lib.util.J2DoP
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.concurrent.AbstractConcurrentEventManager;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet;
+import org.apache.openjpa.lib.util.concurrent.SizedConcurrentHashMap;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.util.Id;
@@ -77,7 +81,21 @@ public abstract class AbstractQueryCache
// default evict policy
public EvictPolicy evictPolicy = EvictPolicy.DEFAULT;
+
+ private QueryStatistics<QueryKey> _stats;
+ private boolean _statsEnabled = false;
+
+ public void setEnableStatistics(boolean enable){
+ _statsEnabled = enable;
+ }
+ public boolean getEnableStatistics(){
+ return _statsEnabled;
+ }
+ public QueryStatistics<QueryKey> getStatistics() {
+ return _stats;
+ }
+
public void initialize(DataCacheManager manager) {
if (evictPolicy == EvictPolicy.TIMESTAMP) {
entityTimestampMap = new ConcurrentHashMap<String,Long>();
@@ -137,6 +155,9 @@ public abstract class AbstractQueryCache
}
public QueryResult get(QueryKey key) {
+ if (_statsEnabled) {
+ _stats.recordExecution(key);
+ }
QueryResult o = getInternal(key);
if (o != null && o.isTimedOut()) {
o = null;
@@ -151,6 +172,9 @@ public abstract class AbstractQueryCache
else
log.trace(s_loc.get("cache-hit", key));
}
+ if (_statsEnabled && o != null) {
+ ((Default<QueryKey>)_stats).recordHit(key);
+ }
return o;
}
@@ -200,6 +224,9 @@ public abstract class AbstractQueryCache
clearInternal();
if (log.isTraceEnabled())
log.trace(s_loc.get("cache-clear", "<query-cache>"));
+ if (_statsEnabled) {
+ _stats.clear();
+ }
}
public void close() {
@@ -339,6 +366,8 @@ public abstract class AbstractQueryCache
}
public void endConfiguration() {
+ _stats = _statsEnabled ? new Default<QueryKey>() :
+ new QueryStatistics.None<QueryKey>();
}
// ---------- AbstractEventManager implementation ----------
@@ -418,4 +447,159 @@ public abstract class AbstractQueryCache
public String getName() {
return _name;
}
+
+ /**
+ * A default implementation of query statistics for the Query result cache.
+ *
+ * Maintains statistics for only a fixed number of queries.
+ * Statistical counts are approximate and not exact (to keep thread synchorization overhead low).
+ *
+ */
+ public static class Default<T> implements QueryStatistics<T> {
+
+ private static final long serialVersionUID = -7889619105916307055L;
+
+ private static final int FIXED_SIZE = 1000;
+ private static final float LOAD_FACTOR = 0.75f;
+ private static final int CONCURRENCY = 16;
+
+ private static final int ARRAY_SIZE = 2;
+ private static final int READ = 0;
+ private static final int HIT = 1;
+
+ private long[] astat = new long[ARRAY_SIZE];
+ private long[] stat = new long[ARRAY_SIZE];
+ private Map<T, long[]> stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY);
+ private Map<T, long[]> astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY);
+ private Date start = new Date();
+ private Date since = start;
+
+ public Set<T> keys() {
+ return stats.keySet();
+ }
+
+ public long getExecutionCount() {
+ return stat[READ];
+ }
+
+ public long getTotalExecutionCount() {
+ return astat[READ];
+ }
+
+ public long getExecutionCount(T query) {
+ return getCount(stats, query, READ);
+ }
+
+ public long getTotalExecutionCount(T query) {
+ return getCount(astats, query, READ);
+ }
+
+ public long getHitCount() {
+ return stat[HIT];
+ }
+
+ public long getTotalHitCount() {
+ return astat[HIT];
+ }
+
+ public long getHitCount(T query) {
+ return getCount(stats, query, HIT);
+ }
+
+ public long getTotalHitCount(T query) {
+ return getCount(astats, query, HIT);
+ }
+
+ private long getCount(Map<T, long[]> target, T query, int i) {
+ long[] row = target.get(query);
+ return (row == null) ? 0 : row[i];
+ }
+
+ public Date since() {
+ return since;
+ }
+
+ public Date start() {
+ return start;
+ }
+
+ public synchronized void reset() {
+ stat = new long[ARRAY_SIZE];
+ stats.clear();
+ since = new Date();
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized void clear() {
+ astat = new long[ARRAY_SIZE];
+ stat = new long[ARRAY_SIZE];
+ stats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY);
+ astats = new SizedConcurrentHashMap(FIXED_SIZE, LOAD_FACTOR, CONCURRENCY);
+ start = new Date();
+ since = start;
+ }
+
+ private void addSample(T query, int index) {
+ stat[index]++;
+ astat[index]++;
+ addSample(stats, query, index);
+ addSample(astats, query, index);
+ }
+
+ private void addSample(Map<T, long[]> target, T query, int i) {
+ long[] row = target.get(query);
+ if (row == null) {
+ row = new long[ARRAY_SIZE];
+ }
+ row[i]++;
+ target.put(query, row);
+ }
+
+ public void recordExecution(T query) {
+ if (query == null)
+ return;
+ addSample(query, READ);
+ }
+
+ public void recordHit(T query) {
+ addSample(query, HIT);
+ }
+
+ public void dump(PrintStream out) {
+ String header = "Query Statistics starting from " + start;
+ out.print(header);
+ if (since == start) {
+ out.println();
+ out.println("Total Query Execution: " + toString(astat));
+ out.println("\tTotal \t\tQuery");
+ } else {
+ out.println(" last reset on " + since);
+ out.println("Total Query Execution since start " +
+ toString(astat) + " since reset " + toString(stat));
+ out.println("\tSince Start \tSince Reset \t\tQuery");
+ }
+ int i = 0;
+ for (T key : stats.keySet()) {
+ i++;
+ long[] arow = astats.get(key);
+ if (since == start) {
+ out.println(i + ". \t" + toString(arow) + " \t" + key);
+ } else {
+ long[] row = stats.get(key);
+ out.println(i + ". \t" + toString(arow) + " \t" + toString(row) + " \t\t" + key);
+ }
+ }
+ }
+
+ long pct(long per, long cent) {
+ if (cent <= 0)
+ return 0;
+ return (100*per)/cent;
+ }
+
+ String toString(long[] row) {
+ return row[READ] + ":" + row[HIT] + "(" + pct(row[HIT], row[READ]) + "%)";
+ }
+ }
+
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DelegatingQueryCache.java Thu Aug 12 02:40:23 2010
@@ -19,6 +19,7 @@
package org.apache.openjpa.datacache;
import org.apache.commons.lang.ObjectUtils;
+import org.apache.openjpa.kernel.QueryStatistics;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
/**
@@ -216,4 +217,14 @@ public class DelegatingQueryCache
throw translate(re);
}
}
+
+ public QueryStatistics<QueryKey> getStatistics() {
+ if (_cache == null)
+ return null;
+ try {
+ return _cache.getStatistics();
+ } catch (RuntimeException re) {
+ throw translate(re);
+ }
+ }
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/QueryCache.java Thu Aug 12 02:40:23 2010
@@ -20,6 +20,7 @@ package org.apache.openjpa.datacache;
import java.util.Map;
+import org.apache.openjpa.kernel.QueryStatistics;
import org.apache.openjpa.lib.util.Closeable;
/**
@@ -135,4 +136,11 @@ public interface QueryCache
* Free the resources used by this cache.
*/
public void close ();
+
+ /**
+ * Gets the simple statistics for query results.
+ * If the statistics gathering is disabled, an empty statistics is returned.
+ * @since 2.1.0
+ */
+ public QueryStatistics<QueryKey> getStatistics();
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractPreparedQueryCacheInstrument.java Thu Aug 12 02:40:23 2010
@@ -19,6 +19,7 @@
package org.apache.openjpa.instrumentation;
import java.util.Date;
+import java.util.Set;
import org.apache.openjpa.kernel.PreparedQueryCache;
import org.apache.openjpa.kernel.QueryStatistics;
@@ -141,6 +142,13 @@ public abstract class AbstractPreparedQu
return null;
}
+ public Set<String> queries() {
+ QueryStatistics<String> stats = getStatistics();
+ if (stats != null)
+ return stats.keys();
+ return null;
+ }
+
public InstrumentationLevel getLevel() {
return InstrumentationLevel.FACTORY;
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/AbstractQueryCacheInstrument.java Thu Aug 12 02:40:23 2010
@@ -19,9 +19,12 @@
package org.apache.openjpa.instrumentation;
import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
-import org.apache.openjpa.datacache.CacheStatistics;
import org.apache.openjpa.datacache.QueryCache;
+import org.apache.openjpa.datacache.QueryKey;
+import org.apache.openjpa.kernel.QueryStatistics;
import org.apache.openjpa.lib.instrumentation.AbstractInstrument;
import org.apache.openjpa.lib.instrumentation.InstrumentationLevel;
@@ -46,94 +49,143 @@ public abstract class AbstractQueryCache
_qc = qc;
}
- // TODO : Cache stats must be added to query cache. They will likely be
- // tracked by a QueryStatistics type when that takes place.
- private CacheStatistics getStatistics() {
+ public void setConfigId(String cid) {
+ _configId = cid;
+ }
+
+ public void setContextRef(String cref) {
+ _configRef = cref;
+ }
+
+ public String getConfigId() {
+ return _configId;
+ }
+
+ public String getContextRef() {
+ return _configRef;
+ }
+
+ public void setPreparedQueryCache(QueryCache qc) {
+ _qc = qc;
+ }
+
+ private QueryStatistics<QueryKey> getStatistics() {
if (_qc == null)
return null;
- return null; // _qc.getStatistics();
+ return _qc.getStatistics();
}
- public long getHitCount() {
- CacheStatistics stats = getStatistics();
+ public long getExecutionCount() {
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
- return stats.getHitCount();
+ return stats.getExecutionCount();
return NO_STATS;
}
-
- public long getReadCount() {
- CacheStatistics stats = getStatistics();
- if (stats != null)
- return stats.getReadCount();
+
+ public long getExecutionCount(String queryKey) {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ if (stats != null) {
+ QueryKey qk = findKey(queryKey);
+ return stats.getExecutionCount(qk);
+ }
return NO_STATS;
}
-
- public long getTotalHitCount() {
- CacheStatistics stats = getStatistics();
+
+ public long getTotalExecutionCount() {
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
- return stats.getTotalHitCount();
+ return stats.getTotalExecutionCount();
return NO_STATS;
}
-
- public long getTotalReadCount() {
- CacheStatistics stats = getStatistics();
- if (stats != null)
- return stats.getTotalReadCount();
+
+ public long getTotalExecutionCount(String queryKey) {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ if (stats != null) {
+ QueryKey qk = findKey(queryKey);
+ return stats.getTotalExecutionCount(qk);
+ }
return NO_STATS;
}
-
- public long getTotalWriteCount() {
- CacheStatistics stats = getStatistics();
+
+ public long getHitCount() {
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
- return stats.getTotalWriteCount();
+ return stats.getHitCount();
return NO_STATS;
}
-
- public long getWriteCount() {
- CacheStatistics stats = getStatistics();
+
+ public long getHitCount(String queryKey) {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ if (stats != null) {
+ QueryKey qk = findKey(queryKey);
+ return stats.getHitCount(qk);
+ }
+ return NO_STATS;
+ }
+
+ public long getTotalHitCount() {
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
- return stats.getWriteCount();
+ return stats.getTotalHitCount();
return NO_STATS;
}
-
+
+ public long getTotalHitCount(String queryKey) {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ if (stats != null) {
+ QueryKey qk = findKey(queryKey);
+ return stats.getTotalHitCount(qk);
+ }
+ return NO_STATS;
+ }
+
public void reset() {
- CacheStatistics stats = getStatistics();
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
stats.reset();
}
public Date sinceDate() {
- CacheStatistics stats = getStatistics();
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
return stats.since();
return null;
}
public Date startDate() {
- CacheStatistics stats = getStatistics();
+ QueryStatistics<QueryKey> stats = getStatistics();
if (stats != null)
return stats.start();
return null;
}
- public String getConfigId() {
- return _configId;
+ /**
+ * Returns all query keys currently tracked in the cache.
+ * @return
+ */
+ public Set<String> queryKeys() {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ if (stats != null) {
+ Set<String> keys = new HashSet<String>();
+ for (QueryKey qk : stats.keys()) {
+ keys.add(qk.toString());
+ }
+ return keys;
+ }
+ return null;
}
- public void setConfigId(String cid) {
- _configId = cid;
- }
-
- public String getContextRef() {
- return _configRef;
- }
-
- public void setContextRef(String cref) {
- _configRef = cref;
+ private QueryKey findKey(String key) {
+ QueryStatistics<QueryKey> stats = getStatistics();
+ for (QueryKey qk : stats.keys()) {
+ if (qk.toString().equals(key.toString())) {
+ return qk;
+ }
+ }
+ return null;
}
-
+
public InstrumentationLevel getLevel() {
return InstrumentationLevel.FACTORY;
}
-
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/PreparedQueryCacheInstrument.java Thu Aug 12 02:40:23 2010
@@ -19,6 +19,7 @@
package org.apache.openjpa.instrumentation;
import java.util.Date;
+import java.util.Set;
public interface PreparedQueryCacheInstrument {
@@ -63,18 +64,7 @@ public interface PreparedQueryCacheInstr
* Returns number of total read requests that has been found since start.
*/
public long getTotalHitCount(String query);
-
- /**
- * Returns the config id for the configuration attached to this cache
- */
- public String getConfigId();
-
- /**
- * Returns the context unique id for the configuration attached to this
- * cache
- */
- public String getContextRef();
-
+
/**
* Resets cache statistics
*/
@@ -89,4 +79,10 @@ public interface PreparedQueryCacheInstr
* Returns date cache statistics collection started.
*/
public Date startDate();
+
+ /**
+ * Returns all queries currently tracked in the cache.
+ * @return
+ */
+ public Set<String> queries();
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/QueryCacheInstrument.java Thu Aug 12 02:40:23 2010
@@ -19,6 +19,7 @@
package org.apache.openjpa.instrumentation;
import java.util.Date;
+import java.util.Set;
/**
* Interface for providing instrumented data cache metrics and operations.
@@ -26,47 +27,47 @@ import java.util.Date;
public interface QueryCacheInstrument {
/**
- * Returns number of total read requests that have been found in cache since
- * last reset.
+ * Returns number of total exec requests since start.
*/
- public long getHitCount();
+ public long getTotalExecutionCount();
/**
- * Returns number of total read requests since last reset
+ * Returns number of total exec requests since start.
*/
- public long getReadCount();
+ public long getTotalExecutionCount(String queryKey);
/**
- * Returns number of total write requests since last reset.
+ * Returns number of total execution requests since last reset
*/
- public long getWriteCount();
+ public long getExecutionCount();
/**
- * Returns number of total read requests since start.
+ * Returns number of total execution requests since last reset
*/
- public long getTotalReadCount();
+ public long getExecutionCount(String queryKey);
/**
- * Returns number of total read requests that has been found since start.
+ * Returns number of total read requests that have been found in cache since
+ * last reset.
*/
- public long getTotalHitCount();
+ public long getHitCount();
/**
- * Returns number of total write requests for the given class since start.
+ * Returns number of total read requests that have been found in cache since
+ * last reset.
*/
- public long getTotalWriteCount();
-
+ public long getHitCount(String queryKey);
+
/**
- * Returns the config id for the configuration attached to this cache
+ * Returns number of total read requests that has been found since start.
*/
- public String getConfigId();
-
+ public long getTotalHitCount();
+
/**
- * Returns the system unique id for the configuration attached to this
- * cache
+ * Returns number of total read requests that has been found since start.
*/
- public String getContextRef();
-
+ public long getTotalHitCount(String queryKey);
+
/**
* Resets cache statistics
*/
@@ -81,4 +82,10 @@ public interface QueryCacheInstrument {
* Returns date cache statistics collection started.
*/
public Date startDate();
+
+ /**
+ * Returns all query keys currently in the cache.
+ * @return
+ */
+ public Set<String> queryKeys();
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/instrumentation/jmx/JMXProvider.java Thu Aug 12 02:40:23 2010
@@ -20,9 +20,11 @@ package org.apache.openjpa.instrumentati
import java.lang.management.ManagementFactory;
import java.util.Map;
+import java.util.Set;
import java.util.Map.Entry;
import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import org.apache.openjpa.lib.instrumentation.AbstractInstrumentationProvider;
@@ -38,12 +40,12 @@ public class JMXProvider
// Aliases for built-in JMX Instrumentation
public static final String[] JMX_INSTRUMENT_ALIASES = {
"DataCache", "org.apache.openjpa.instrumentation.jmx.DataCacheJMXInstrument",
- "QueryCache", "org.apache.openjpa.insrumentation.jmx.QueryCacheJMXInstrument",
- "QuerySQLCache", "org.apache.openjpa.insrumentation.jmx.PreparedQueryCacheJMXInstrument"
+ "QueryCache", "org.apache.openjpa.instrumentation.jmx.QueryCacheJMXInstrument",
+ "QuerySQLCache", "org.apache.openjpa.instrumentation.jmx.PreparedQueryCacheJMXInstrument"
};
/**
- * The standard mbean package for OpenJPA
+ * The MBean domain for OpenJPA
*/
public static final String MBEAN_DOMAIN = "org.apache.openjpa";
@@ -80,14 +82,33 @@ public class JMXProvider
if (mbs == null) {
throw new UserException("jmx-server-failed-creation");
}
+ setStarted(true);
} catch (Throwable t) {
throw new UserException("jmx-server-unavailable",t);
}
}
+ /**
+ * Stops all instruments registered with this provider and releases the
+ * reference to the Platform MBean server instance.
+ */
@Override
public void stop() {
- // no-op with the built in MBean server
+ if (isStarted()) {
+ Set<Instrument> instruments = getInstruments();
+ if (instruments != null && instruments.size() > 0) {
+ for (Instrument inst : instruments) {
+ stopInstrument(inst);
+ }
+ }
+ // The MBean server factory does appear to ref count properly so the
+ // platform server cannot released from the factory once it is acquired.
+ // Multiple attempts to capture and release the server will result in a
+ // runtime exception.
+ // MBeanServerFactory.releaseMBeanServer(getMBeanServer());
+ // _mbs = null;
+ setStarted(false);
+ }
}
/**
@@ -125,6 +146,7 @@ public class JMXProvider
public void startInstrument(Instrument instrument) {
if (!instrument.isStarted()) {
registerMBean((JMXInstrument)instrument);
+ instrument.setStarted(true);
}
}
@@ -135,6 +157,7 @@ public class JMXProvider
if (instrument.isStarted() || force) {
try {
getMBeanServer().unregisterMBean(((JMXInstrument)instrument).getObjectName());
+ instrument.setStarted(false);
} catch (Exception e) {
// If force, swallow the exception since the bean may not even
// be registered.
Modified: openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/instrumentation/Instrument.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/instrumentation/Instrument.java?rev=984633&r1=984632&r2=984633&view=diff
==============================================================================
--- openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/instrumentation/Instrument.java (original)
+++ openjpa/trunk/openjpa-lib/src/main/java/org/apache/openjpa/lib/instrumentation/Instrument.java Thu Aug 12 02:40:23 2010
@@ -87,6 +87,12 @@ public interface Instrument {
public boolean isStarted();
/**
+ * Sets whether the instrument is an available state.
+ * @param started
+ */
+ public void setStarted(boolean started);
+
+ /**
* Starts the instrument. Typically this will be performed through the provider,
* but in some cases an instrument will have its own specialized startup.
*/