You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2011/04/05 16:37:23 UTC
svn commit: r1089061 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/
main/java/org/apache/jackrabbit/core/jmx/
main/java/org/apache/jackrabbit/core/jmx/query/
main/java/org/apache/jackrabbit/core/query/ test/java/org/a...
Author: jukka
Date: Tue Apr 5 14:37:22 2011
New Revision: 1089061
URL: http://svn.apache.org/viewvc?rev=1089061&view=rev
Log:
JCR-2936: JMX Bindings for Jackrabbit
Patch by Alex Parvulescu
Added:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JackrabbitBaseMBean.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistry.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryUtils.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStat.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManager.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerBase.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImplMBean.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/QueryStatManagerTest.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java?rev=1089061&r1=1089060&r2=1089061&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Apr 5 14:37:22 2011
@@ -81,6 +81,8 @@ import org.apache.jackrabbit.core.fs.Fil
import org.apache.jackrabbit.core.fs.FileSystemResource;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.id.NodeIdFactory;
+import org.apache.jackrabbit.core.jmx.JmxRegistry;
+import org.apache.jackrabbit.core.jmx.JmxRegistryImpl;
import org.apache.jackrabbit.core.lock.LockManager;
import org.apache.jackrabbit.core.lock.LockManagerImpl;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
@@ -231,6 +233,8 @@ public class RepositoryImpl extends Abst
*/
private final CacheManager cacheMgr = new CacheManager();
+ private final JmxRegistry jmxRegistry = new JmxRegistryImpl();
+
/**
* Chanel for posting create workspace messages.
*/
@@ -355,6 +359,9 @@ public class RepositoryImpl extends Abst
// initialize system search manager
getSystemSearchManager(repConfig.getDefaultWorkspaceName());
+ //this has to be live before initSecurityManager(), to be able to track all the queries
+ initJmxRegistry();
+
// Initialise the security manager;
initSecurityManager();
@@ -461,6 +468,10 @@ public class RepositoryImpl extends Abst
return cacheMgr;
}
+ public JmxRegistry getJmxRegistry(){
+ return jmxRegistry;
+ }
+
/**
* Creates the {@link org.apache.jackrabbit.core.security.JackrabbitSecurityManager SecurityManager}
* of this <code>Repository</code> and adds it to the repository context.
@@ -1192,6 +1203,8 @@ public class RepositoryImpl extends Abst
context.getTimer().cancel();
+ jmxRegistry.stop();
+
log.info("Repository has been shutdown");
}
@@ -1452,6 +1465,9 @@ public class RepositoryImpl extends Abst
return new GarbageCollector(context.getDataStore(), ipmList, sessions);
}
+ protected void initJmxRegistry(){
+ this.jmxRegistry.start();
+ }
//-----------------------------------------------------------< Repository >
/**
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JackrabbitBaseMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JackrabbitBaseMBean.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JackrabbitBaseMBean.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JackrabbitBaseMBean.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx;
+
+/**
+ * http://www.oracle.com/technetwork/java/javase/tech/best-practices-jsp-136021.
+ * html
+ *
+ * This should be the base for any MBean Services built for Jackrabbit
+ *
+ */
+public interface JackrabbitBaseMBean {
+
+ String BASE_NAME = "org.apache.jackrabbit";
+
+ boolean isEnabled();
+
+ void setEnabled(boolean enabled);
+
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistry.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistry.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistry.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx;
+
+import javax.management.ObjectName;
+
+import org.apache.jackrabbit.core.jmx.query.QueryStatManager;
+
+/**
+ * JMX Mbean registration service
+ *
+ */
+public interface JmxRegistry {
+
+ /**
+ * starts the service
+ */
+ void start();
+
+ /**
+ * stops the service
+ */
+ void stop();
+
+ /**
+ * Registers a new MBEan under the given name
+ *
+ * @param bean
+ * to be registered
+ * @param name
+ * @throws Exception
+ */
+ void register(JackrabbitBaseMBean bean, ObjectName name) throws Exception;
+
+ /**
+ * Unregisters a bean
+ *
+ * @param name
+ * @throws Exception
+ */
+ void unregister(ObjectName name) throws Exception;
+
+ QueryStatManager getQueryStatManager();
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryImpl.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryImpl.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.jackrabbit.core.jmx.query.QueryStatManager;
+import org.apache.jackrabbit.core.jmx.query.QueryStatManagerImpl;
+import org.apache.jackrabbit.core.jmx.query.QueryStatManagerImplMBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JmxRegistry default implementation
+ *
+ */
+public class JmxRegistryImpl implements JmxRegistry {
+
+ private static Logger log = LoggerFactory.getLogger(JmxRegistryImpl.class);
+
+ private MBeanServer server;
+
+ private List<ObjectName> registry = new ArrayList<ObjectName>();
+
+ private QueryStatManagerImpl queryStatManager;
+
+ public JmxRegistryImpl() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.jackrabbit.core.jmx.JmxRegistry#start()
+ */
+ public void start() {
+ server = ManagementFactory.getPlatformMBeanServer();
+ try {
+ queryStatManager = new QueryStatManagerImpl();
+ register(queryStatManager, new ObjectName(
+ QueryStatManagerImplMBean.NAME));
+ log.info("Started JMX Registry");
+ } catch (Exception e) {
+ queryStatManager = null;
+ log.error("Unable to start JMX Registry", e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.jackrabbit.core.jmx.JmxRegistry#stop()
+ */
+ public void stop() {
+ if (server == null) {
+ return;
+ }
+
+ for (ObjectName o : registry) {
+ try {
+ server.unregisterMBean(o);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ registry.clear();
+ server = null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.jackrabbit.core.jmx.JmxRegistry#register(org.apache.jackrabbit
+ * .core.jmx.JackrabbitMBean, javax.management.ObjectName)
+ */
+ public void register(JackrabbitBaseMBean bean, ObjectName name)
+ throws Exception {
+ this.server.registerMBean(bean, name);
+ this.registry.add(name);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.jackrabbit.core.jmx.JmxRegistry#unregister(javax.management
+ * .ObjectName)
+ */
+ public void unregister(ObjectName name) throws Exception {
+ if (server == null || !server.isRegistered(name)) {
+ return;
+ }
+ registry.remove(name);
+ server.unregisterMBean(name);
+ }
+
+ public QueryStatManager getQueryStatManager() {
+ return queryStatManager;
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryUtils.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryUtils.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/JmxRegistryUtils.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx;
+
+import org.apache.jackrabbit.core.jmx.query.QueryStat;
+import org.apache.jackrabbit.core.query.QueryImpl;
+
+/**
+ * Utilities related to JMX
+ *
+ */
+public class JmxRegistryUtils {
+
+ /**
+ * private constructor
+ */
+ private JmxRegistryUtils() {
+ //
+ }
+
+ /**
+ * Transforms a Query into a QueryStat
+ *
+ * @param q
+ * the query
+ * @param duration
+ * duration of the query
+ * @return the stat object
+ */
+ public static QueryStat buildQueryStat(QueryImpl q, long duration) {
+ return new QueryStat(q.getLanguage(), q.getStatement(), duration);
+ }
+
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStat.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStat.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStat.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStat.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx.query;
+
+import java.io.Serializable;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * Object that holds statistical info about a query.
+ *
+ */
+public class QueryStat implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * lazy, computed at call time
+ */
+ private long position;
+
+ /**
+ * the time that the query was created
+ */
+ private final Date creationTime;
+
+ /**
+ * run duration
+ */
+ private final long duration;
+
+ /**
+ * query language
+ */
+ private final String language;
+
+ /**
+ * query statement
+ */
+ private final String statement;
+
+ public QueryStat(final String language, final String statement,
+ long duration) {
+ this.duration = duration;
+ this.language = language;
+ this.statement = statement;
+
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(System.currentTimeMillis() - duration);
+ this.creationTime = c.getTime();
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public String getLanguage() {
+ return language;
+ }
+
+ public String getStatement() {
+ return statement;
+ }
+
+ public String getCreationTime() {
+ return creationTime.toString();
+ }
+
+ public long getPosition() {
+ return position;
+ }
+
+ public void setPosition(long position) {
+ this.position = position;
+ }
+
+ @Override
+ public String toString() {
+ return "QueryStat [creationTime=" + creationTime + ", duration="
+ + duration + ", language=" + language + ", statement="
+ + statement + "]";
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManager.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManager.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManager.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx.query;
+
+/**
+ *
+ * Extends QueryStatManagerBase with write access to the query log. <br>
+ *
+ */
+public interface QueryStatManager extends QueryStatManagerBase {
+
+ /**
+ * log a {@link QueryStat} to the service if it is enabled
+ *
+ * @param query
+ */
+ void logQuery(QueryStat query);
+
+ QueryStat[] getTopQueries();
+
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerBase.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerBase.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerBase.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx.query;
+
+/**
+ *
+ * Service that tracks statistics for queries. <br>
+ *
+ * It acts as a <b>Top X</b> longest running queries.
+ *
+ */
+public interface QueryStatManagerBase {
+
+ /**
+ * @return how big the <b>Top X</b> queue is
+ */
+ int getQueueSize();
+
+ /**
+ * Change the <b>Top X</b> queue size
+ *
+ * @param size
+ * the new size
+ */
+ void setQueueSize(int size);
+
+ /**
+ * clears the queue
+ */
+ void clearQueue();
+
+ /**
+ * If this service is currently registering stats
+ *
+ * @return <code>true</code> if the service is enabled
+ */
+ boolean isEnabled();
+
+ /**
+ * Enables/Disables the service
+ *
+ * @param enabled
+ */
+ void setEnabled(boolean enabled);
+
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImpl.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImpl.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImpl.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx.query;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.PriorityQueue;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+/**
+ * Default {@link QueryStatManager} implementation
+ *
+ */
+public class QueryStatManagerImpl implements QueryStatManagerImplMBean,
+ QueryStatManager {
+
+ private final static Comparator<QueryStat> comparator = new QueryStatComp();
+
+ private final static Comparator<QueryStat> comparatorRev = Collections
+ .reverseOrder(comparator);
+
+ private int queueSize = 15;
+
+ private PriorityQueue<QueryStat> queries = new PriorityQueue<QueryStat>(
+ queueSize + 1, new QueryStatComp());
+
+ private boolean enabled;
+
+ /**
+ * Default constructor. This will disable the monitoring service
+ */
+ public QueryStatManagerImpl() {
+ this(false);
+ }
+
+ /**
+ * Constructor allowing the enabling/disabling of the service
+ *
+ * @param isEnabled
+ */
+ public QueryStatManagerImpl(boolean isEnabled) {
+ this.enabled = isEnabled;
+ }
+
+ public int getQueueSize() {
+ return queueSize;
+ }
+
+ public synchronized void setQueueSize(int size) {
+ this.queueSize = size;
+ this.queries = new PriorityQueue<QueryStat>(this.queueSize + 1,
+ comparator);
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ this.queries = new PriorityQueue<QueryStat>(this.queueSize + 1,
+ comparator);
+ }
+
+ public QueryStat[] getTopQueries() {
+ // TODO cache this call
+ QueryStat[] top = queries.toArray(new QueryStat[queries.size()]);
+ Arrays.sort(top, comparatorRev);
+ for (int i = 0; i < top.length; i++) {
+ top[i].setPosition(i + 1);
+ }
+ return top;
+ }
+
+ public TabularData getQueries() {
+ TabularDataSupport tds = null;
+ try {
+ CompositeType ct = QueryStatCompositeTypeFactory.getCompositeType();
+
+ TabularType tt = new TabularType(QueryStat.class.getName(),
+ "Query History", ct, QueryStatCompositeTypeFactory.index);
+ tds = new TabularDataSupport(tt);
+
+ for (QueryStat q : getTopQueries()) {
+ tds.put(new CompositeDataSupport(ct,
+ QueryStatCompositeTypeFactory.names,
+ QueryStatCompositeTypeFactory.getValues(q)));
+ }
+ return tds;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public synchronized void logQuery(QueryStat stat) {
+ if (!enabled) {
+ return;
+ }
+ queries.add(stat);
+ if (queries.size() > queueSize) {
+ queries.remove();
+ }
+ }
+
+ private static class QueryStatComp implements Comparator<QueryStat> {
+
+ public int compare(QueryStat o1, QueryStat o2) {
+ return new Long(o1.getDuration()).compareTo(o2.getDuration());
+ }
+ }
+
+ private static class QueryStatCompositeTypeFactory {
+
+ private final static String[] index = { "position" };
+
+ private final static String[] names = { "position", "duration",
+ "language", "statement", "creationTime" };
+
+ private final static String[] descriptions = { "position", "duration",
+ "language", "statement", "creationTime" };
+
+ private final static OpenType[] types = { SimpleType.LONG,
+ SimpleType.LONG, SimpleType.STRING, SimpleType.STRING,
+ SimpleType.STRING };
+
+ public static CompositeType getCompositeType() throws OpenDataException {
+ return new CompositeType(QueryStat.class.getName(),
+ QueryStat.class.getName(), names, descriptions, types);
+ }
+
+ public static Object[] getValues(QueryStat q) {
+ return new Object[] { q.getPosition(), q.getDuration(),
+ q.getLanguage(), q.getStatement(), q.getCreationTime() };
+ }
+ }
+
+ public void clearQueue() {
+ this.queries.clear();
+ }
+}
Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImplMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImplMBean.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImplMBean.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/jmx/query/QueryStatManagerImplMBean.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx.query;
+
+import javax.management.openmbean.TabularData;
+
+import org.apache.jackrabbit.core.jmx.JackrabbitBaseMBean;
+
+/**
+ * JMX Binding for the {@link QueryStatManagerImpl}. <br>
+ *
+ */
+public interface QueryStatManagerImplMBean extends JackrabbitBaseMBean,
+ QueryStatManagerBase {
+
+ String NAME = BASE_NAME + ":type=QueryStats";
+
+ TabularData getQueries();
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java?rev=1089061&r1=1089060&r2=1089061&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryImpl.java Tue Apr 5 14:37:22 2011
@@ -35,6 +35,8 @@ import javax.jcr.query.InvalidQueryExcep
import javax.jcr.query.QueryResult;
import javax.jcr.version.VersionException;
+import org.apache.jackrabbit.core.jmx.JmxRegistryUtils;
+import org.apache.jackrabbit.core.jmx.query.QueryStatManager;
import org.apache.jackrabbit.core.session.SessionContext;
import org.apache.jackrabbit.core.session.SessionOperation;
import org.apache.jackrabbit.spi.Path;
@@ -134,8 +136,13 @@ public class QueryImpl extends AbstractQ
return "query.execute(" + statement + ")";
}
});
+ time = System.currentTimeMillis() - time;
+ QueryStatManager qsm = sessionContext.getRepository().getJmxRegistry()
+ .getQueryStatManager();
+ if (qsm != null) {
+ qsm.logQuery(JmxRegistryUtils.buildQueryStat(this, time));
+ }
if (log.isDebugEnabled()) {
- time = System.currentTimeMillis() - time;
NumberFormat format = NumberFormat.getNumberInstance();
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(2);
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java?rev=1089061&r1=1089060&r2=1089061&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryObjectModelImpl.java Tue Apr 5 14:37:22 2011
@@ -32,6 +32,8 @@ import javax.jcr.query.qom.QueryObjectMo
import javax.jcr.query.qom.Source;
import org.apache.jackrabbit.commons.query.QueryObjectModelBuilderRegistry;
+import org.apache.jackrabbit.core.jmx.JmxRegistryUtils;
+import org.apache.jackrabbit.core.jmx.query.QueryStatManager;
import org.apache.jackrabbit.core.query.lucene.LuceneQueryFactory;
import org.apache.jackrabbit.core.query.lucene.SearchIndex;
import org.apache.jackrabbit.core.query.lucene.join.QueryEngine;
@@ -123,6 +125,12 @@ public class QueryObjectModelImpl extend
QueryResult qr = engine.execute(getColumns(), getSource(),
getConstraint(), getOrderings(), offset, limit);
time = System.currentTimeMillis() - time;
+
+ QueryStatManager qsm = sessionContext.getRepository().getJmxRegistry()
+ .getQueryStatManager();
+ if (qsm != null) {
+ qsm.logQuery(JmxRegistryUtils.buildQueryStat(this, time));
+ }
if (log.isDebugEnabled()) {
NumberFormat format = NumberFormat.getNumberInstance();
format.setMinimumFractionDigits(2);
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/QueryStatManagerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/QueryStatManagerTest.java?rev=1089061&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/QueryStatManagerTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/jmx/QueryStatManagerTest.java Tue Apr 5 14:37:22 2011
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.jmx;
+
+import javax.jcr.query.Query;
+
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.jmx.query.QueryStat;
+import org.apache.jackrabbit.core.jmx.query.QueryStatManager;
+import org.apache.jackrabbit.core.query.AbstractQueryTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Performs various JMX test cases.
+ */
+public class QueryStatManagerTest extends AbstractQueryTest {
+
+ private static Logger log = LoggerFactory
+ .getLogger(QueryStatManagerTest.class);
+
+ public void testLogDuration() throws Exception {
+
+ int queueSize = 15;
+ int runTimes = 50;
+
+ RepositoryImpl r = (RepositoryImpl) superuser.getRepository();
+ QueryStatManager qsm = r.getJmxRegistry().getQueryStatManager();
+ qsm.setQueueSize(queueSize);
+ qsm.setEnabled(false);
+
+ // just to warm up the cache
+ double initial = doStatTest(runTimes);
+
+ qsm.setEnabled(false);
+ double off = doStatTest(runTimes);
+
+ qsm.setEnabled(true);
+ double on = doStatTest(runTimes);
+
+ log.info("Logging times: initial=" + initial
+ + ", without QueryStatManager = " + off
+ + ", with QueryStatManager = " + on);
+
+ QueryStat[] top = qsm.getTopQueries();
+ assertNotNull("Query Top should not be null", top);
+ assertEquals("Query Top should contain entries ",
+ Math.min(queueSize, runTimes), top.length);
+ }
+
+ private double doStatTest(int times) throws Exception {
+
+ long total = 0;
+ for (int i = 0; i < times; i++) {
+ long start = System.currentTimeMillis();
+ Query q = qm.createQuery("SELECT * FROM [nt:base]", Query.JCR_SQL2);
+ q.execute();
+ long dur = System.currentTimeMillis() - start;
+ total += dur;
+ }
+ return (double) total / times;
+ }
+}