diff options
Diffstat (limited to 'dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor')
12 files changed, 0 insertions, 2605 deletions
diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java deleted file mode 100644 index e2f1414..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java +++ /dev/null @@ -1,158 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Method; - -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement. - * By extending this class, one can intercept queries and update statements by overriding the {@link #createStatement(Object, Method, Object[], Object, long)} - * method. - * @version 1.0 - */ -public abstract class AbstractCreateStatementInterceptor extends JdbcInterceptor { - protected static final String CREATE_STATEMENT = "createStatement"; - protected static final int CREATE_STATEMENT_IDX = 0; - protected static final String PREPARE_STATEMENT = "prepareStatement"; - protected static final int PREPARE_STATEMENT_IDX = 1; - protected static final String PREPARE_CALL = "prepareCall"; - protected static final int PREPARE_CALL_IDX = 2; - - protected static final String[] STATEMENT_TYPES = {CREATE_STATEMENT, PREPARE_STATEMENT, PREPARE_CALL}; - protected static final int STATEMENT_TYPE_COUNT = STATEMENT_TYPES.length; - - protected static final String EXECUTE = "execute"; - protected static final String EXECUTE_QUERY = "executeQuery"; - protected static final String EXECUTE_UPDATE = "executeUpdate"; - protected static final String EXECUTE_BATCH = "executeBatch"; - - protected static final String[] EXECUTE_TYPES = {EXECUTE, EXECUTE_QUERY, EXECUTE_UPDATE, EXECUTE_BATCH}; - - public AbstractCreateStatementInterceptor() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (compare(CLOSE_VAL,method)) { - closeInvoked(); - return super.invoke(proxy, method, args); - } else { - boolean process = false; - process = isStatement(method, process); - if (process) { - long start = System.currentTimeMillis(); - Object statement = super.invoke(proxy,method,args); - long delta = System.currentTimeMillis() - start; - return createStatement(proxy,method,args,statement, delta); - } else { - return super.invoke(proxy,method,args); - } - } - } - - /** - * This method will be invoked after a successful statement creation. This method can choose to return a wrapper - * around the statement or return the statement itself. - * If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces. - * {@link java.sql.Statement}, {@link java.sql.PreparedStatement} or {@link java.sql.CallableStatement} - * @param proxy the actual proxy object - * @param method the method that was called. It will be one of the methods defined in {@link #STATEMENT_TYPES} - * @param args the arguments to the method - * @param statement the statement that the underlying connection created - * @param time Elapsed time - * @return a {@link java.sql.Statement} object - */ - public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time); - - /** - * Method invoked when the operation {@link java.sql.Connection#close()} is invoked. - */ - public abstract void closeInvoked(); - - /** - * Returns true if the method that is being invoked matches one of the statement types. - * - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean isStatement(Method method, boolean process){ - return process(STATEMENT_TYPES, method, process); - } - - /** - * Returns true if the method that is being invoked matches one of the execute types. - * - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean isExecute(Method method, boolean process){ - return process(EXECUTE_TYPES, method, process); - } - - /* - * Returns true if the method that is being invoked matches one of the method names passed in - * @param names list of method names that we want to intercept - * @param method the method being invoked on the proxy - * @param process boolean result used for recursion - * @return returns true if the method name matched - */ - protected boolean process(String[] names, Method method, boolean process) { - final String name = method.getName(); - for (int i=0; (!process) && i<names.length; i++) { - process = compare(names[i],name); - } - return process; - } - - /** - * no-op for this interceptor. no state is stored. - */ - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - // NOOP - } -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java deleted file mode 100644 index 374969d..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java +++ /dev/null @@ -1,285 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -/** - * Abstract class that wraps statements and intercepts query executions. - * - */ -public abstract class AbstractQueryReport extends AbstractCreateStatementInterceptor { - //logger - private static final Log log = LogFactory.getLog(AbstractQueryReport.class); - - /** - * The threshold in milliseconds. If the query is faster than this, we don't measure it - */ - protected long threshold = 1000; //don't report queries less than this - - /** - * the constructors that are used to create statement proxies - */ - protected static final Constructor<?>[] constructors = - new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT]; - - - public AbstractQueryReport() { - super(); - } - - /** - * Invoked when prepareStatement has been called and completed. - * @param sql - the string used to prepare the statement with - * @param time - the time it took to invoke prepare - */ - protected abstract void prepareStatement(String sql, long time); - - /** - * Invoked when prepareCall has been called and completed. - * @param query - the string used to prepare the statement with - * @param time - the time it took to invoke prepare - */ - protected abstract void prepareCall(String query, long time); - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch failed. - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param t the exception that happened - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportFailedQuery(String query, Object[] args, final String name, long start, Throwable t) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was within the timing threshold - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param delta the time the execution took - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportQuery(String query, Object[] args, final String name, long start, long delta) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was exceeded the timing threshold - * @param query the query that was executed and failed - * @param args the arguments to the execution - * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)} - * @param start the time the query execution started - * @param delta the time the execution took - * @return - the SQL that was executed or the string "batch" if it was a batch execution - */ - protected String reportSlowQuery(String query, Object[] args, final String name, long start, long delta) { - //extract the query string - String sql = (query==null && args!=null && args.length>0)?(String)args[0]:query; - //if we do batch execution, then we name the query 'batch' - if (sql==null && compare(EXECUTE_BATCH,name)) { - sql = "batch"; - } - return sql; - } - - /** - * returns the query measure threshold. - * This value is in milliseconds. If the query is faster than this threshold than it wont be accounted for - * @return the threshold in milliseconds - */ - public long getThreshold() { - return threshold; - } - - /** - * Sets the query measurement threshold. The value is in milliseconds. - * If the query goes faster than this threshold it will not be recorded. - * @param threshold set to -1 to record every query. Value is in milliseconds. - */ - public void setThreshold(long threshold) { - this.threshold = threshold; - } - - /** - * Creates a constructor for a proxy class, if one doesn't already exist - * @param idx - the index of the constructor - * @param clazz - the interface that the proxy will implement - * @return - returns a constructor used to create new instances - * @throws NoSuchMethodException Constructor not found - */ - protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException { - if (constructors[idx]==null) { - Class<?> proxyClass = Proxy.getProxyClass(SlowQueryReport.class.getClassLoader(), new Class[] {clazz}); - constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return constructors[idx]; - } - - /** - * Creates a statement interceptor to monitor query response times - */ - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - try { - Object result = null; - String name = method.getName(); - String sql = null; - Constructor<?> constructor = null; - if (compare(CREATE_STATEMENT,name)) { - //createStatement - constructor = getConstructor(CREATE_STATEMENT_IDX,Statement.class); - }else if (compare(PREPARE_STATEMENT,name)) { - //prepareStatement - sql = (String)args[0]; - constructor = getConstructor(PREPARE_STATEMENT_IDX,PreparedStatement.class); - if (sql!=null) { - prepareStatement(sql, time); - } - }else if (compare(PREPARE_CALL,name)) { - //prepareCall - sql = (String)args[0]; - constructor = getConstructor(PREPARE_CALL_IDX,CallableStatement.class); - prepareCall(sql,time); - }else { - //do nothing, might be a future unsupported method - //so we better bail out and let the system continue - return statement; - } - result = constructor.newInstance(new Object[] { new StatementProxy(statement,sql) }); - return result; - }catch (Exception x) { - log.warn("Unable to create statement proxy for slow query report.",x); - } - return statement; - } - - - /** - * Class to measure query execute time - * - */ - protected class StatementProxy implements InvocationHandler { - protected boolean closed = false; - protected Object delegate; - protected final String query; - public StatementProxy(Object parent, String query) { - this.delegate = parent; - this.query = query; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - //get the name of the method for comparison - final String name = method.getName(); - //was close invoked? - boolean close = compare(JdbcInterceptor.CLOSE_VAL,name); - //allow close to be called multiple times - if (close && closed) return null; - //are we calling isClosed? - if (compare(JdbcInterceptor.ISCLOSED_VAL,name)) return Boolean.valueOf(closed); - //if we are calling anything else, bail out - if (closed) throw new SQLException("Statement closed."); - boolean process = false; - //check to see if we are about to execute a query - process = isExecute( method, process); - //if we are executing, get the current time - long start = (process)?System.currentTimeMillis():0; - Object result = null; - try { - //execute the query - result = method.invoke(delegate,args); - }catch (Throwable t) { - reportFailedQuery(query,args,name,start,t); - if (t instanceof InvocationTargetException - && t.getCause() != null) { - throw t.getCause(); - } else { - throw t; - } - } - //measure the time - long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE; - //see if we meet the requirements to measure - if (delta>threshold) { - try { - //report the slow query - reportSlowQuery(query, args, name, start, delta); - }catch (Exception t) { - if (log.isWarnEnabled()) log.warn("Unable to process slow query",t); - } - } else if (process) { - reportQuery(query, args, name, start, delta); - } - //perform close cleanup - if (close) { - closed=true; - delegate = null; - } - return result; - } - } - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java deleted file mode 100644 index 95049c6..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java +++ /dev/null @@ -1,184 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Method; -import java.sql.SQLException; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.DataSourceFactory; -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -import org.apache.tomcat.jdbc.pool.PoolConfiguration; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Interceptor that keep track of connection state to avoid roundtrips to the database. - * The {@link org.apache.tomcat.jdbc.pool.ConnectionPool} is optimized to do as little work as possible. - * The pool itself doesn't remember settings like {@link java.sql.Connection#setAutoCommit(boolean)}, - * {@link java.sql.Connection#setReadOnly(boolean)}, {@link java.sql.Connection#setCatalog(String)} or - * {@link java.sql.Connection#setTransactionIsolation(int)}. It relies on the application to remember how and when - * these settings have been applied. - * In the cases where the application code doesn't know or want to keep track of the state, this interceptor helps cache the - * state, and it also avoids roundtrips to the database asking for it. - * - */ - -public class ConnectionState extends JdbcInterceptor { - private static final Log log = LogFactory.getLog(ConnectionState.class); - - protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly","getCatalog"}; - protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly","setCatalog"}; - - protected Boolean autoCommit = null; - protected Integer transactionIsolation = null; - protected Boolean readOnly = null; - protected String catalog = null; - - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - if (parent==null || con==null) { - //we are resetting, reset our defaults - autoCommit = null; - transactionIsolation = null; - readOnly = null; - catalog = null; - return; - } - PoolConfiguration poolProperties = parent.getPoolProperties(); - if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) { - try { - if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) { - con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation()); - transactionIsolation = Integer.valueOf(poolProperties.getDefaultTransactionIsolation()); - } - }catch (SQLException x) { - transactionIsolation = null; - log.error("Unable to reset transaction isolation state to connection.",x); - } - } - if (poolProperties.getDefaultReadOnly()!=null) { - try { - if (readOnly==null || readOnly.booleanValue()!=poolProperties.getDefaultReadOnly().booleanValue()) { - con.getConnection().setReadOnly(poolProperties.getDefaultReadOnly().booleanValue()); - readOnly = poolProperties.getDefaultReadOnly(); - } - }catch (SQLException x) { - readOnly = null; - log.error("Unable to reset readonly state to connection.",x); - } - } - if (poolProperties.getDefaultAutoCommit()!=null) { - try { - if (autoCommit==null || autoCommit.booleanValue()!=poolProperties.getDefaultAutoCommit().booleanValue()) { - con.getConnection().setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue()); - autoCommit = poolProperties.getDefaultAutoCommit(); - } - }catch (SQLException x) { - autoCommit = null; - log.error("Unable to reset autocommit state to connection.",x); - } - } - if (poolProperties.getDefaultCatalog()!=null) { - try { - if (catalog==null || (!catalog.equals(poolProperties.getDefaultCatalog()))) { - con.getConnection().setCatalog(poolProperties.getDefaultCatalog()); - catalog = poolProperties.getDefaultCatalog(); - } - }catch (SQLException x) { - catalog = null; - log.error("Unable to reset default catalog state to connection.",x); - } - } - - } - - - @Override - public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) { - //we are resetting, reset our defaults - autoCommit = null; - transactionIsolation = null; - readOnly = null; - catalog = null; - super.disconnected(parent, con, finalizing); - } - - - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - String name = method.getName(); - boolean read = false; - int index = -1; - for (int i=0; (!read) && i<readState.length; i++) { - read = compare(name,readState[i]); - if (read) index = i; - } - boolean write = false; - for (int i=0; (!write) && (!read) && i<writeState.length; i++) { - write = compare(name,writeState[i]); - if (write) index = i; - } - Object result = null; - if (read) { - switch (index) { - case 0:{result = autoCommit; break;} - case 1:{result = transactionIsolation; break;} - case 2:{result = readOnly; break;} - case 3:{result = catalog; break;} - default: // NOOP - } - //return cached result, if we have it - if (result!=null) return result; - } - - result = super.invoke(proxy, method, args); - if (read || write) { - switch (index) { - case 0:{autoCommit = (Boolean) (read?result:args[0]); break;} - case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;} - case 2:{readOnly = (Boolean)(read?result:args[0]); break;} - case 3:{catalog = (String)(read?result:args[0]); break;} - } - } - return result; - } - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java deleted file mode 100644 index 7aec0b4..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/QueryTimeoutInterceptor.java +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Method; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Map; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; - -public class QueryTimeoutInterceptor extends AbstractCreateStatementInterceptor { - private static Log log = LogFactory.getLog(QueryTimeoutInterceptor.class); - int timeout = 1; - - @Override - public void setProperties(Map<String,InterceptorProperty> properties) { - super.setProperties(properties); - InterceptorProperty p = properties.get("queryTimeout"); - if (p!=null) timeout = p.getValueAsInt(timeout); - } - - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - if (statement instanceof Statement && timeout > 0) { - Statement s = (Statement)statement; - try { - s.setQueryTimeout(timeout); - }catch (SQLException x) { - log.warn("[QueryTimeoutInterceptor] Unable to set query timeout:"+x.getMessage(),x); - } - } - return statement; - } - - @Override - public void closeInvoked() { - } - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java deleted file mode 100644 index 6c6981e..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java +++ /dev/null @@ -1,112 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Method; - -import org.apache.tomcat.jdbc.pool.JdbcInterceptor; -import org.apache.tomcat.jdbc.pool.PooledConnection; -import org.apache.tomcat.jdbc.pool.ProxyConnection; - -/** - * Class that resets the abandoned timer on any activity on the - * Connection or any successful query executions. - * This interceptor is useful for when you have a {@link org.apache.tomcat.jdbc.pool.PoolConfiguration#setRemoveAbandonedTimeout(int)} - * that is fairly low, and you want to reset the abandoned time each time any operation on the connection is performed - * This is useful for batch processing programs that use connections for extensive amount of times. - * - */ -public class ResetAbandonedTimer extends AbstractQueryReport { - - public ResetAbandonedTimer() { - } - - public boolean resetTimer() { - boolean result = false; - JdbcInterceptor interceptor = this.getNext(); - while (interceptor!=null && result==false) { - if (interceptor instanceof ProxyConnection) { - PooledConnection con = ((ProxyConnection)interceptor).getConnection(); - if (con!=null) { - con.setTimestamp(System.currentTimeMillis()); - result = true; - } else { - break; - } - } - interceptor = interceptor.getNext(); - } - return result; - } - - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - Object result = super.invoke(proxy, method, args); - resetTimer(); - return result; - } - - @Override - protected void prepareCall(String query, long time) { - resetTimer(); - } - - @Override - protected void prepareStatement(String sql, long time) { - resetTimer(); - - } - - @Override - public void closeInvoked() { - resetTimer(); - } - - @Override - protected String reportQuery(String query, Object[] args, String name,long start, long delta) { - resetTimer(); - return super.reportQuery(query, args, name, start, delta); - } - - @Override - protected String reportSlowQuery(String query, Object[] args, String name,long start, long delta) { - resetTimer(); - return super.reportSlowQuery(query, args, name, start, delta); - } -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java deleted file mode 100644 index 23fa3fa..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java +++ /dev/null @@ -1,516 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; - -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 org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Slow query report interceptor. Tracks timing of query executions. - * @version 1.0 - */ -public class SlowQueryReport extends AbstractQueryReport { - //logger - private static final Log log = LogFactory.getLog(SlowQueryReport.class); - - /** - * we will be keeping track of query stats on a per pool basis - */ - protected static final ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>> perPoolStats = - new ConcurrentHashMap<>(); - /** - * the queries that are used for this interceptor. - */ - protected volatile ConcurrentHashMap<String,QueryStats> queries = null; - /** - * Maximum number of queries we will be storing - */ - protected int maxQueries= 1000; //don't store more than this amount of queries - - /** - * Flag to enable disable logging of slow queries - */ - protected boolean logSlow = true; - - /** - * Flag to enable disable logging of failed queries - */ - protected boolean logFailed = false; - - /** - * Sort QueryStats by last invocation time - */ - protected final Comparator<QueryStats> queryStatsComparator = new QueryStatsComparator(); - - /** - * Returns the query stats for a given pool - * @param poolname - the name of the pool we want to retrieve stats for - * @return a hash map containing statistics for 0 to maxQueries - */ - public static ConcurrentHashMap<String,QueryStats> getPoolStats(String poolname) { - return perPoolStats.get(poolname); - } - - /** - * Creates a slow query report interceptor - */ - public SlowQueryReport() { - super(); - } - - public void setMaxQueries(int maxQueries) { - this.maxQueries = maxQueries; - } - - - @Override - protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) { - String sql = super.reportFailedQuery(query, args, name, start, t); - if (this.maxQueries > 0 ) { - long now = System.currentTimeMillis(); - long delta = now - start; - QueryStats qs = this.getQueryStats(sql); - if (qs != null) { - qs.failure(delta, now); - if (isLogFailed() && log.isWarnEnabled()) { - log.warn("Failed Query Report SQL="+sql+"; time="+delta+" ms;"); - } - } - } - return sql; - } - - @Override - protected String reportQuery(String query, Object[] args, final String name, long start, long delta) { - String sql = super.reportQuery(query, args, name, start, delta); - if (this.maxQueries > 0 ) { - QueryStats qs = this.getQueryStats(sql); - if (qs != null) qs.add(delta, start); - } - return sql; - } - - @Override - protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) { - String sql = super.reportSlowQuery(query, args, name, start, delta); - if (this.maxQueries > 0 ) { - QueryStats qs = this.getQueryStats(sql); - if (qs != null) { - qs.add(delta, start); - if (isLogSlow() && log.isWarnEnabled()) { - log.warn("Slow Query Report SQL="+sql+"; time="+delta+" ms;"); - } - } - } - return sql; - } - - /** - * invoked when the connection receives the close request - * Not used for now. - */ - @Override - public void closeInvoked() { - // NOOP - } - - @Override - public void prepareStatement(String sql, long time) { - if (this.maxQueries > 0 ) { - QueryStats qs = getQueryStats(sql); - if (qs != null) qs.prepare(time); - } - } - - @Override - public void prepareCall(String sql, long time) { - if (this.maxQueries > 0 ) { - QueryStats qs = getQueryStats(sql); - if (qs != null) qs.prepare(time); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void poolStarted(ConnectionPool pool) { - super.poolStarted(pool); - //see if we already created a map for this pool - queries = SlowQueryReport.perPoolStats.get(pool.getName()); - if (queries==null) { - //create the map to hold our stats - //however TODO we need to improve the eviction - //selection - queries = new ConcurrentHashMap<>(); - if (perPoolStats.putIfAbsent(pool.getName(), queries)!=null) { - //there already was one - queries = SlowQueryReport.perPoolStats.get(pool.getName()); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public void poolClosed(ConnectionPool pool) { - perPoolStats.remove(pool.getName()); - super.poolClosed(pool); - } - - protected QueryStats getQueryStats(String sql) { - if (sql==null) sql = ""; - ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries; - if (queries==null) { - if (log.isWarnEnabled()) log.warn("Connection has already been closed or abandoned"); - return null; - } - QueryStats qs = queries.get(sql); - if (qs == null) { - qs = new QueryStats(sql); - if (queries.putIfAbsent(sql,qs)!=null) { - qs = queries.get(sql); - } else { - //we added a new element, see if we need to remove the oldest - if (queries.size() > maxQueries) { - removeOldest(queries); - } - } - } - return qs; - } - - /** - * Sort QueryStats by last invocation time - * @param queries The queries map - */ - protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) { - ArrayList<QueryStats> list = new ArrayList<>(queries.values()); - Collections.sort(list, queryStatsComparator); - int removeIndex = 0; - while (queries.size() > maxQueries) { - String sql = list.get(removeIndex).getQuery(); - queries.remove(sql); - if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql); - removeIndex++; - } - } - - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - super.reset(parent, con); - if (parent!=null) - queries = SlowQueryReport.perPoolStats.get(parent.getName()); - else - queries = null; - } - - - public boolean isLogSlow() { - return logSlow; - } - - public void setLogSlow(boolean logSlow) { - this.logSlow = logSlow; - } - - public boolean isLogFailed() { - return logFailed; - } - - public void setLogFailed(boolean logFailed) { - this.logFailed = logFailed; - } - - @Override - public void setProperties(Map<String, InterceptorProperty> properties) { - super.setProperties(properties); - final String threshold = "threshold"; - final String maxqueries= "maxQueries"; - final String logslow = "logSlow"; - final String logfailed = "logFailed"; - InterceptorProperty p1 = properties.get(threshold); - InterceptorProperty p2 = properties.get(maxqueries); - InterceptorProperty p3 = properties.get(logslow); - InterceptorProperty p4 = properties.get(logfailed); - if (p1!=null) { - setThreshold(Long.parseLong(p1.getValue())); - } - if (p2!=null) { - setMaxQueries(Integer.parseInt(p2.getValue())); - } - if (p3!=null) { - setLogSlow(Boolean.parseBoolean(p3.getValue())); - } - if (p4!=null) { - setLogFailed(Boolean.parseBoolean(p4.getValue())); - } - } - - - public static class QueryStats { - static final String[] FIELD_NAMES = new String[] { - "query", - "nrOfInvocations", - "maxInvocationTime", - "maxInvocationDate", - "minInvocationTime", - "minInvocationDate", - "totalInvocationTime", - "failures", - "prepareCount", - "prepareTime", - "lastInvocation" - }; - - static final String[] FIELD_DESCRIPTIONS = new String[] { - "The SQL query", - "The number of query invocations, a call to executeXXX", - "The longest time for this query in milliseconds", - "The time and date for when the longest query took place", - "The shortest time for this query in milliseconds", - "The time and date for when the shortest query took place", - "The total amount of milliseconds spent executing this query", - "The number of failures for this query", - "The number of times this query was prepared (prepareStatement/prepareCall)", - "The total number of milliseconds spent preparing this query", - "The date and time of the last invocation" - }; - - static final OpenType<?>[] FIELD_TYPES = new OpenType[] { - SimpleType.STRING, - SimpleType.INTEGER, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.INTEGER, - SimpleType.LONG, - SimpleType.LONG - }; - - private final String query; - private volatile int nrOfInvocations; - private volatile long maxInvocationTime = Long.MIN_VALUE; - private volatile long maxInvocationDate; - private volatile long minInvocationTime = Long.MAX_VALUE; - private volatile long minInvocationDate; - private volatile long totalInvocationTime; - private volatile long failures; - private volatile int prepareCount; - private volatile long prepareTime; - private volatile long lastInvocation = 0; - - public static String[] getFieldNames() { - return FIELD_NAMES; - } - - public static String[] getFieldDescriptions() { - return FIELD_DESCRIPTIONS; - } - - public static OpenType<?>[] getFieldTypes() { - return FIELD_TYPES; - } - - @Override - public String toString() { - SimpleDateFormat sdf = - new SimpleDateFormat("d MMM yyyy HH:mm:ss z", Locale.US); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - StringBuilder buf = new StringBuilder("QueryStats[query:"); - buf.append(query); - buf.append(", nrOfInvocations:"); - buf.append(nrOfInvocations); - buf.append(", maxInvocationTime:"); - buf.append(maxInvocationTime); - buf.append(", maxInvocationDate:"); - buf.append(sdf.format(new java.util.Date(maxInvocationDate))); - buf.append(", minInvocationTime:"); - buf.append(minInvocationTime); - buf.append(", minInvocationDate:"); - buf.append(sdf.format(new java.util.Date(minInvocationDate))); - buf.append(", totalInvocationTime:"); - buf.append(totalInvocationTime); - buf.append(", averageInvocationTime:"); - buf.append((float)totalInvocationTime / (float)nrOfInvocations); - buf.append(", failures:"); - buf.append(failures); - buf.append(", prepareCount:"); - buf.append(prepareCount); - buf.append(", prepareTime:"); - buf.append(prepareTime); - buf.append("]"); - return buf.toString(); - } - - public CompositeDataSupport getCompositeData(final CompositeType type) throws OpenDataException{ - Object[] values = new Object[] { - query, - Integer.valueOf(nrOfInvocations), - Long.valueOf(maxInvocationTime), - Long.valueOf(maxInvocationDate), - Long.valueOf(minInvocationTime), - Long.valueOf(minInvocationDate), - Long.valueOf(totalInvocationTime), - Long.valueOf(failures), - Integer.valueOf(prepareCount), - Long.valueOf(prepareTime), - Long.valueOf(lastInvocation) - }; - return new CompositeDataSupport(type,FIELD_NAMES,values); - } - - public QueryStats(String query) { - this.query = query; - } - - public void prepare(long invocationTime) { - prepareCount++; - prepareTime+=invocationTime; - - } - - public void add(long invocationTime, long now) { - //not thread safe, but don't sacrifice performance for this kind of stuff - maxInvocationTime = Math.max(invocationTime, maxInvocationTime); - if (maxInvocationTime == invocationTime) { - maxInvocationDate = now; - } - minInvocationTime = Math.min(invocationTime, minInvocationTime); - if (minInvocationTime==invocationTime) { - minInvocationDate = now; - } - nrOfInvocations++; - totalInvocationTime+=invocationTime; - lastInvocation = now; - } - - public void failure(long invocationTime, long now) { - add(invocationTime,now); - failures++; - - } - - public String getQuery() { - return query; - } - - public int getNrOfInvocations() { - return nrOfInvocations; - } - - public long getMaxInvocationTime() { - return maxInvocationTime; - } - - public long getMaxInvocationDate() { - return maxInvocationDate; - } - - public long getMinInvocationTime() { - return minInvocationTime; - } - - public long getMinInvocationDate() { - return minInvocationDate; - } - - public long getTotalInvocationTime() { - return totalInvocationTime; - } - - @Override - public int hashCode() { - return query.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (other instanceof QueryStats) { - QueryStats qs = (QueryStats)other; - return qs.query.equals(this.query); - } - return false; - } - - public boolean isOlderThan(QueryStats other) { - return this.lastInvocation < other.lastInvocation; - } - } - - /** Compare QueryStats by their lastInvocation value. QueryStats that - * have never been updated, have a lastInvocation value of {@code 0} - * which should be handled as the newest possible invocation. - */ - private static class QueryStatsComparator implements Comparator<QueryStats> { - - @Override - public int compare(QueryStats stats1, QueryStats stats2) { - return Long.compare(handleZero(stats1.lastInvocation), - handleZero(stats2.lastInvocation)); - } - - private static long handleZero(long value) { - return value == 0 ? Long.MAX_VALUE : value; - } - - } - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java deleted file mode 100644 index 60b48a0..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java +++ /dev/null @@ -1,338 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.management.ManagementFactory; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -import javax.management.InstanceAlreadyExistsException; -import javax.management.InstanceNotFoundException; -import javax.management.ListenerNotFoundException; -import javax.management.MBeanException; -import javax.management.MBeanNotificationInfo; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.RuntimeOperationsException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; -import org.apache.tomcat.jdbc.pool.PooledConnection; -/** - * Publishes data to JMX and provides notifications - * when failures happen. - * - */ -public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean{ - public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY"; - public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY"; - - public static final String objectNameAttribute = "objectName"; - - protected static volatile CompositeType SLOW_QUERY_TYPE; - - private static final Log log = LogFactory.getLog(SlowQueryReportJmx.class); - - - protected static final ConcurrentHashMap<String,SlowQueryReportJmxMBean> mbeans = - new ConcurrentHashMap<>(); - - - //==============================JMX STUFF======================== - protected volatile NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport(); - - @Override - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { - notifier.addNotificationListener(listener, filter, handback); - } - - - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - return notifier.getNotificationInfo(); - } - - @Override - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { - notifier.removeNotificationListener(listener); - - } - - @Override - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { - notifier.removeNotificationListener(listener, filter, handback); - - } - - - //==============================JMX STUFF======================== - - protected String poolName = null; - - protected static final AtomicLong notifySequence = new AtomicLong(0); - - protected boolean notifyPool = true; - - protected ConnectionPool pool = null; - - protected static CompositeType getCompositeType() { - if (SLOW_QUERY_TYPE==null) { - try { - SLOW_QUERY_TYPE = new CompositeType( - SlowQueryReportJmx.class.getName(), - "Composite data type for query statistics", - QueryStats.getFieldNames(), - QueryStats.getFieldDescriptions(), - QueryStats.getFieldTypes()); - }catch (OpenDataException x) { - log.warn("Unable to initialize composite data type for JMX stats and notifications.",x); - } - } - return SLOW_QUERY_TYPE; - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - super.reset(parent, con); - if (parent!=null) { - poolName = parent.getName(); - pool = parent; - registerJmx(); - } - } - - - @Override - public void poolClosed(ConnectionPool pool) { - this.poolName = pool.getName(); - deregisterJmx(); - super.poolClosed(pool); - } - - @Override - public void poolStarted(ConnectionPool pool) { - this.pool = pool; - super.poolStarted(pool); - this.poolName = pool.getName(); - } - - @Override - protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) { - query = super.reportFailedQuery(query, args, name, start, t); - if (isLogFailed()) notifyJmx(query,FAILED_QUERY_NOTIFICATION); - return query; - } - - protected void notifyJmx(String query, String type) { - try { - long sequence = notifySequence.incrementAndGet(); - - if (isNotifyPool()) { - if (this.pool!=null && this.pool.getJmxPool()!=null) { - this.pool.getJmxPool().notify(type, query); - } - } else { - if (notifier!=null) { - Notification notification = - new Notification(type, - this, - sequence, - System.currentTimeMillis(), - query); - - notifier.sendNotification(notification); - } - } - } catch (RuntimeOperationsException e) { - if (log.isDebugEnabled()) { - log.debug("Unable to send failed query notification.",e); - } - } - } - - @Override - protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) { - query = super.reportSlowQuery(query, args, name, start, delta); - if (isLogSlow()) notifyJmx(query,SLOW_QUERY_NOTIFICATION); - return query; - } - - /** - * JMX operation - return the names of all the pools - * @return - all the names of pools that we have stored data for - */ - public String[] getPoolNames() { - Set<String> keys = perPoolStats.keySet(); - return keys.toArray(new String[0]); - } - - /** - * JMX operation - return the name of the pool - * @return the name of the pool, unique within the JVM - */ - public String getPoolName() { - return poolName; - } - - - public boolean isNotifyPool() { - return notifyPool; - } - - public void setNotifyPool(boolean notifyPool) { - this.notifyPool = notifyPool; - } - - /** - * JMX operation - remove all stats for this connection pool - */ - public void resetStats() { - ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName); - if (queries!=null) { - Iterator<String> it = queries.keySet().iterator(); - while (it.hasNext()) it.remove(); - } - } - - /** - * JMX operation - returns all the queries we have collected. - * @return - the slow query report as composite data. - */ - @Override - public CompositeData[] getSlowQueriesCD() throws OpenDataException { - CompositeDataSupport[] result = null; - ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName); - if (queries!=null) { - Set<Map.Entry<String,QueryStats>> stats = queries.entrySet(); - if (stats!=null) { - result = new CompositeDataSupport[stats.size()]; - Iterator<Map.Entry<String,QueryStats>> it = stats.iterator(); - int pos = 0; - while (it.hasNext()) { - Map.Entry<String,QueryStats> entry = it.next(); - QueryStats qs = entry.getValue(); - result[pos++] = qs.getCompositeData(getCompositeType()); - } - } - } - return result; - } - - protected void deregisterJmx() { - try { - if (mbeans.remove(poolName)!=null) { - ObjectName oname = getObjectName(getClass(),poolName); - ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname); - } - } catch (MBeanRegistrationException e) { - log.debug("Jmx deregistration failed.",e); - } catch (InstanceNotFoundException e) { - log.debug("Jmx deregistration failed.",e); - } catch (MalformedObjectNameException e) { - log.warn("Jmx deregistration failed.",e); - } catch (RuntimeOperationsException e) { - log.warn("Jmx deregistration failed.",e); - } - - } - - - public ObjectName getObjectName(Class<?> clazz, String poolName) throws MalformedObjectNameException { - ObjectName oname; - Map<String,InterceptorProperty> properties = getProperties(); - if (properties != null && properties.containsKey(objectNameAttribute)) { - oname = new ObjectName(properties.get(objectNameAttribute).getValue()); - } else { - oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+clazz.getName()+",name=" + poolName); - } - return oname; - } - - protected void registerJmx() { - try { - //only if we notify the pool itself - if (isNotifyPool()) { - - } else if (getCompositeType()!=null) { - ObjectName oname = getObjectName(getClass(),poolName); - if (mbeans.putIfAbsent(poolName, this)==null) { - ManagementFactory.getPlatformMBeanServer().registerMBean(this, oname); - } - } else { - log.warn(SlowQueryReport.class.getName()+ "- No JMX support, composite type was not found."); - } - } catch (MalformedObjectNameException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (RuntimeOperationsException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (MBeanException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (InstanceAlreadyExistsException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } catch (NotCompliantMBeanException e) { - log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e); - } - } - - @Override - public void setProperties(Map<String, InterceptorProperty> properties) { - super.setProperties(properties); - final String threshold = "notifyPool"; - InterceptorProperty p1 = properties.get(threshold); - if (p1!=null) { - this.setNotifyPool(Boolean.parseBoolean(p1.getValue())); - } - } - - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java deleted file mode 100644 index 202d06e..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* 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.tomcat.jdbc.pool.interceptor; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.OpenDataException; - -public interface SlowQueryReportJmxMBean { - public CompositeData[] getSlowQueriesCD() throws OpenDataException; -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java deleted file mode 100644 index e98d3b6..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java +++ /dev/null @@ -1,358 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Interceptor that caches {@code PreparedStatement} and/or - * {@code CallableStatement} instances on a connection. - */ -public class StatementCache extends StatementDecoratorInterceptor { - protected static final String[] ALL_TYPES = new String[] {PREPARE_STATEMENT,PREPARE_CALL}; - protected static final String[] CALLABLE_TYPE = new String[] {PREPARE_CALL}; - protected static final String[] PREPARED_TYPE = new String[] {PREPARE_STATEMENT}; - protected static final String[] NO_TYPE = new String[] {}; - - protected static final String STATEMENT_CACHE_ATTR = StatementCache.class.getName() + ".cache"; - - /*begin properties for the statement cache*/ - private boolean cachePrepared = true; - private boolean cacheCallable = false; - private int maxCacheSize = 50; - private PooledConnection pcon; - private String[] types; - - - public boolean isCachePrepared() { - return cachePrepared; - } - - public boolean isCacheCallable() { - return cacheCallable; - } - - public int getMaxCacheSize() { - return maxCacheSize; - } - - public String[] getTypes() { - return types; - } - - public AtomicInteger getCacheSize() { - return cacheSize; - } - - @Override - public void setProperties(Map<String, InterceptorProperty> properties) { - super.setProperties(properties); - InterceptorProperty p = properties.get("prepared"); - if (p!=null) cachePrepared = p.getValueAsBoolean(cachePrepared); - p = properties.get("callable"); - if (p!=null) cacheCallable = p.getValueAsBoolean(cacheCallable); - p = properties.get("max"); - if (p!=null) maxCacheSize = p.getValueAsInt(maxCacheSize); - if (cachePrepared && cacheCallable) { - this.types = ALL_TYPES; - } else if (cachePrepared) { - this.types = PREPARED_TYPE; - } else if (cacheCallable) { - this.types = CALLABLE_TYPE; - } else { - this.types = NO_TYPE; - } - - } - /*end properties for the statement cache*/ - - /*begin the cache size*/ - private static ConcurrentHashMap<ConnectionPool,AtomicInteger> cacheSizeMap = - new ConcurrentHashMap<>(); - - private AtomicInteger cacheSize; - - @Override - public void poolStarted(ConnectionPool pool) { - cacheSizeMap.putIfAbsent(pool, new AtomicInteger(0)); - super.poolStarted(pool); - } - - @Override - public void poolClosed(ConnectionPool pool) { - cacheSizeMap.remove(pool); - super.poolClosed(pool); - } - /*end the cache size*/ - - /*begin the actual statement cache*/ - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - super.reset(parent, con); - if (parent==null) { - cacheSize = null; - this.pcon = null; - } else { - cacheSize = cacheSizeMap.get(parent); - this.pcon = con; - if (!pcon.getAttributes().containsKey(STATEMENT_CACHE_ATTR)) { - ConcurrentHashMap<CacheKey,CachedStatement> cache = - new ConcurrentHashMap<>(); - pcon.getAttributes().put(STATEMENT_CACHE_ATTR,cache); - } - } - } - - @Override - public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) { - @SuppressWarnings("unchecked") - ConcurrentHashMap<CacheKey,CachedStatement> statements = - (ConcurrentHashMap<CacheKey,CachedStatement>)con.getAttributes().get(STATEMENT_CACHE_ATTR); - - if (statements!=null) { - for (Map.Entry<CacheKey, CachedStatement> p : statements.entrySet()) { - closeStatement(p.getValue()); - } - statements.clear(); - } - - super.disconnected(parent, con, finalizing); - } - - public void closeStatement(CachedStatement st) { - if (st==null) return; - st.forceClose(); - } - - @Override - protected Object createDecorator(Object proxy, Method method, Object[] args, - Object statement, Constructor<?> constructor, String sql) - throws InstantiationException, IllegalAccessException, InvocationTargetException { - boolean process = process(this.types, method, false); - if (process) { - Object result = null; - CachedStatement statementProxy = new CachedStatement((Statement)statement,sql); - result = constructor.newInstance(new Object[] { statementProxy }); - statementProxy.setActualProxy(result); - statementProxy.setConnection(proxy); - statementProxy.setConstructor(constructor); - statementProxy.setCacheKey(createCacheKey(method, args)); - return result; - } else { - return super.createDecorator(proxy, method, args, statement, constructor, sql); - } - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - boolean process = process(this.types, method, false); - if (process && args.length>0 && args[0] instanceof String) { - CachedStatement statement = isCached(method, args); - if (statement!=null) { - //remove it from the cache since it is used - removeStatement(statement); - return statement.getActualProxy(); - } else { - return super.invoke(proxy, method, args); - } - } else { - return super.invoke(proxy,method,args); - } - } - - public CachedStatement isCached(Method method, Object[] args) { - @SuppressWarnings("unchecked") - ConcurrentHashMap<CacheKey,CachedStatement> cache = - (ConcurrentHashMap<CacheKey,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - return cache.get(createCacheKey(method, args)); - } - - public boolean cacheStatement(CachedStatement proxy) { - @SuppressWarnings("unchecked") - ConcurrentHashMap<CacheKey,CachedStatement> cache = - (ConcurrentHashMap<CacheKey,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - if (proxy.getCacheKey()==null) { - return false; - } else if (cache.containsKey(proxy.getCacheKey())) { - return false; - } else if (cacheSize.get()>=maxCacheSize) { - return false; - } else if (cacheSize.incrementAndGet()>maxCacheSize) { - cacheSize.decrementAndGet(); - return false; - } else { - //cache the statement - cache.put(proxy.getCacheKey(), proxy); - return true; - } - } - - public boolean removeStatement(CachedStatement proxy) { - @SuppressWarnings("unchecked") - ConcurrentHashMap<CacheKey,CachedStatement> cache = - (ConcurrentHashMap<CacheKey,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR); - if (cache.remove(proxy.getCacheKey()) != null) { - cacheSize.decrementAndGet(); - return true; - } else { - return false; - } - } - /*end the actual statement cache*/ - - - protected class CachedStatement extends StatementDecoratorInterceptor.StatementProxy<Statement> { - boolean cached = false; - CacheKey key; - public CachedStatement(Statement parent, String sql) { - super(parent, sql); - } - - @Override - public void closeInvoked() { - //should we cache it - boolean shouldClose = true; - if (cacheSize.get() < maxCacheSize) { - //cache a proxy so that we don't reuse the facade - CachedStatement proxy = new CachedStatement(getDelegate(),getSql()); - proxy.setCacheKey(getCacheKey()); - try { - // clear Resultset - ResultSet result = getDelegate().getResultSet(); - if (result != null && !result.isClosed()) { - result.close(); - } - //create a new facade - Object actualProxy = getConstructor().newInstance(new Object[] { proxy }); - proxy.setActualProxy(actualProxy); - proxy.setConnection(getConnection()); - proxy.setConstructor(getConstructor()); - if (cacheStatement(proxy)) { - proxy.cached = true; - shouldClose = false; - } - } catch (Exception x) { - removeStatement(proxy); - } - } - if (shouldClose) { - super.closeInvoked(); - } - closed = true; - delegate = null; - - } - - public void forceClose() { - removeStatement(this); - super.closeInvoked(); - } - - public CacheKey getCacheKey() { - return key; - } - - public void setCacheKey(CacheKey cacheKey) { - key = cacheKey; - } - - } - - protected CacheKey createCacheKey(Method method, Object[] args) { - return createCacheKey(method.getName(), args); - } - - protected CacheKey createCacheKey(String methodName, Object[] args) { - CacheKey key = null; - if (compare(PREPARE_STATEMENT, methodName)) { - key = new CacheKey(PREPARE_STATEMENT, args); - } else if (compare(PREPARE_CALL, methodName)) { - key = new CacheKey(PREPARE_CALL, args); - } - return key; - } - - - private static final class CacheKey { - private final String stmtType; - private final Object[] args; - private CacheKey(String type, Object[] methodArgs) { - stmtType = type; - args = methodArgs; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Arrays.hashCode(args); - result = prime * result - + ((stmtType == null) ? 0 : stmtType.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - CacheKey other = (CacheKey) obj; - if (!Arrays.equals(args, other.args)) - return false; - if (stmtType == null) { - if (other.stmtType != null) - return false; - } else if (!stmtType.equals(other.stmtType)) - return false; - return true; - } - } -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java deleted file mode 100644 index e3b160b..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java +++ /dev/null @@ -1,342 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; - -/** - * Implementation of <b>JdbcInterceptor</b> that proxies resultSets and statements. - * @author Guillermo Fernandes - */ -public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor { - - private static final Log logger = LogFactory.getLog(StatementDecoratorInterceptor.class); - - protected static final String EXECUTE_QUERY = "executeQuery"; - protected static final String GET_GENERATED_KEYS = "getGeneratedKeys"; - protected static final String GET_RESULTSET = "getResultSet"; - - protected static final String[] RESULTSET_TYPES = {EXECUTE_QUERY, GET_GENERATED_KEYS, GET_RESULTSET}; - - /** - * the constructors that are used to create statement proxies - */ - protected static final Constructor<?>[] constructors = new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT]; - - /** - * the constructor to create the resultSet proxies - */ - protected static Constructor<?> resultSetConstructor = null; - - @Override - public void closeInvoked() { - // nothing to do - } - - /** - * Creates a constructor for a proxy class, if one doesn't already exist - * - * @param idx - * - the index of the constructor - * @param clazz - * - the interface that the proxy will implement - * @return - returns a constructor used to create new instances - * @throws NoSuchMethodException Constructor not found - */ - protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException { - if (constructors[idx] == null) { - Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), - new Class[] { clazz }); - constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return constructors[idx]; - } - - protected Constructor<?> getResultSetConstructor() throws NoSuchMethodException { - if (resultSetConstructor == null) { - Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(), - new Class[] { ResultSet.class }); - resultSetConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class }); - } - return resultSetConstructor; - } - - /** - * Creates a statement interceptor to monitor query response times - */ - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - try { - String name = method.getName(); - Constructor<?> constructor = null; - String sql = null; - if (compare(CREATE_STATEMENT, name)) { - // createStatement - constructor = getConstructor(CREATE_STATEMENT_IDX, Statement.class); - } else if (compare(PREPARE_STATEMENT, name)) { - // prepareStatement - constructor = getConstructor(PREPARE_STATEMENT_IDX, PreparedStatement.class); - sql = (String)args[0]; - } else if (compare(PREPARE_CALL, name)) { - // prepareCall - constructor = getConstructor(PREPARE_CALL_IDX, CallableStatement.class); - sql = (String)args[0]; - } else { - // do nothing, might be a future unsupported method - // so we better bail out and let the system continue - return statement; - } - return createDecorator(proxy, method, args, statement, constructor, sql); - } catch (Exception x) { - if (x instanceof InvocationTargetException) { - Throwable cause = x.getCause(); - if (cause instanceof ThreadDeath) { - throw (ThreadDeath) cause; - } - if (cause instanceof VirtualMachineError) { - throw (VirtualMachineError) cause; - } - } - logger.warn("Unable to create statement proxy for slow query report.", x); - } - return statement; - } - - /** - * Creates a proxy for a Statement. - * - * @param proxy The proxy object on which the method that triggered - * the creation of the statement was called. - * @param method The method that was called on the proxy - * @param args The arguments passed as part of the method call to - * the proxy - * @param statement The statement object that is to be proxied - * @param constructor The constructor for the desired proxy - * @param sql The sql of of the statement - * - * @return A new proxy for the Statement - * @throws InstantiationException Couldn't instantiate object - * @throws IllegalAccessException Inaccessible constructor - * @throws InvocationTargetException Exception thrown from constructor - */ - protected Object createDecorator(Object proxy, Method method, Object[] args, - Object statement, Constructor<?> constructor, String sql) - throws InstantiationException, IllegalAccessException, InvocationTargetException { - Object result = null; - StatementProxy<Statement> statementProxy = - new StatementProxy<>((Statement)statement,sql); - result = constructor.newInstance(new Object[] { statementProxy }); - statementProxy.setActualProxy(result); - statementProxy.setConnection(proxy); - statementProxy.setConstructor(constructor); - return result; - } - - protected boolean isExecuteQuery(String methodName) { - return EXECUTE_QUERY.equals(methodName); - } - - protected boolean isExecuteQuery(Method method) { - return isExecuteQuery(method.getName()); - } - - protected boolean isResultSet(Method method, boolean process) { - return process(RESULTSET_TYPES, method, process); - } - - /** - * Class to measure query execute time. - */ - protected class StatementProxy<T extends java.sql.Statement> implements InvocationHandler { - - protected boolean closed = false; - protected T delegate; - private Object actualProxy; - private Object connection; - private String sql; - private Constructor<?> constructor; - - public StatementProxy(T delegate, String sql) { - this.delegate = delegate; - this.sql = sql; - } - public T getDelegate() { - return this.delegate; - } - - public String getSql() { - return sql; - } - - public void setConnection(Object proxy) { - this.connection = proxy; - } - public Object getConnection() { - return this.connection; - } - - public void setActualProxy(Object proxy){ - this.actualProxy = proxy; - } - public Object getActualProxy() { - return this.actualProxy; - } - - - public Constructor<?> getConstructor() { - return constructor; - } - public void setConstructor(Constructor<?> constructor) { - this.constructor = constructor; - } - public void closeInvoked() { - if (getDelegate()!=null) { - try { - getDelegate().close(); - }catch (SQLException ignore) { - } - } - closed = true; - delegate = null; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (compare(TOSTRING_VAL,method)) { - return toString(); - } - // was close invoked? - boolean close = compare(CLOSE_VAL, method); - // allow close to be called multiple times - if (close && closed) - return null; - // are we calling isClosed? - if (compare(ISCLOSED_VAL, method)) - return Boolean.valueOf(closed); - // if we are calling anything else, bail out - if (closed) - throw new SQLException("Statement closed."); - if (compare(GETCONNECTION_VAL,method)){ - return connection; - } - boolean process = false; - process = isResultSet(method, process); - // check to see if we are about to execute a query - // if we are executing, get the current time - Object result = null; - try { - // perform close cleanup - if (close) { - closeInvoked(); - } else { - // execute the query - result = method.invoke(delegate, args); - } - } catch (Throwable t) { - if (t instanceof InvocationTargetException - && t.getCause() != null) { - throw t.getCause(); - } else { - throw t; - } - } - if (process && result != null) { - Constructor<?> cons = getResultSetConstructor(); - result = cons.newInstance(new Object[]{new ResultSetProxy(actualProxy, result)}); - } - return result; - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(StatementProxy.class.getName()); - buf.append("[Proxy="); - buf.append(System.identityHashCode(this)); - buf.append("; Sql="); - buf.append(getSql()); - buf.append("; Delegate="); - buf.append(getDelegate()); - buf.append("; Connection="); - buf.append(getConnection()); - buf.append("]"); - return buf.toString(); - } - } - - protected class ResultSetProxy implements InvocationHandler { - - private Object st; - private Object delegate; - - public ResultSetProxy(Object st, Object delegate) { - this.st = st; - this.delegate = delegate; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if (method.getName().equals("getStatement")) { - return this.st; - } else { - try { - return method.invoke(this.delegate, args); - } catch (Throwable t) { - if (t instanceof InvocationTargetException - && t.getCause() != null) { - throw t.getCause(); - } else { - throw t; - } - } - } - } - } -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java deleted file mode 100644 index 6535139..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java +++ /dev/null @@ -1,136 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * openecomp - * ================================================================================ - * Copyright (C) 2016 - 2017 AT&T - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -/* - * 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.tomcat.jdbc.pool.interceptor; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.sql.Statement; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.apache.juli.logging.Log; -import org.apache.juli.logging.LogFactory; -import org.apache.tomcat.jdbc.pool.ConnectionPool; -import org.apache.tomcat.jdbc.pool.PoolProperties; -import org.apache.tomcat.jdbc.pool.PooledConnection; - -/** - * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()} - * Useful for applications that dont close the associated statements after being done with a connection. - * - */ -public class StatementFinalizer extends AbstractCreateStatementInterceptor { - private static final Log log = LogFactory.getLog(StatementFinalizer.class); - - protected List<StatementEntry> statements = new LinkedList<>(); - - private boolean logCreationStack = false; - - @Override - public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) { - try { - if (statement instanceof Statement) - statements.add(new StatementEntry((Statement)statement)); - }catch (ClassCastException x) { - //ignore this one - } - return statement; - } - - @SuppressWarnings("null") // st is not null when used - @Override - public void closeInvoked() { - while (statements.size()>0) { - StatementEntry ws = statements.remove(0); - Statement st = ws.getStatement(); - boolean shallClose = false; - try { - shallClose = st!=null && (!st.isClosed()); - if (shallClose) { - st.close(); - } - } catch (Exception ignore) { - if (log.isDebugEnabled()) { - log.debug("Unable to closed statement upon connection close.",ignore); - } - } finally { - if (logCreationStack && shallClose) { - log.warn("Statement created, but was not closed at:", ws.getAllocationStack()); - } - } - } - } - - @Override - public void setProperties(Map<String, PoolProperties.InterceptorProperty> properties) { - super.setProperties(properties); - - PoolProperties.InterceptorProperty logProperty = properties.get("trace"); - if (null != logProperty) { - logCreationStack = logProperty.getValueAsBoolean(logCreationStack); - } - } - - @Override - public void reset(ConnectionPool parent, PooledConnection con) { - statements.clear(); - super.reset(parent, con); - } - - protected class StatementEntry { - private WeakReference<Statement> statement; - private Throwable allocationStack; - - public StatementEntry(Statement statement) { - this.statement = new WeakReference<>(statement); - if (logCreationStack) { - this.allocationStack = new Throwable(); - } - } - - public Statement getStatement() { - return statement.get(); - } - - public Throwable getAllocationStack() { - return allocationStack; - } - } - - -} diff --git a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml b/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml deleted file mode 100644 index 0cca7ad..0000000 --- a/dblib/common/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ============LICENSE_START======================================================= - openecomp - ================================================================================ - Copyright (C) 2016 - 2017 AT&T - ================================================================================ - Licensed 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. - ============LICENSE_END========================================================= - --> - -<!-- - 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. ---> -<mbeans-descriptors> - - <mbean description="Reports " domain="tomcat.jdbc" group="jdbc-pool" name="SlowQueryReportJmx" - type="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx"> - - <attribute description="The name of the connection pool this Jmx bean is representing" name="poolName" type="java.lang.String" writeable="false"/> - <attribute description="List of all registered connections pools" name="poolNames" type="[java.lang.String;" writeable="false"/> - <attribute description="All the recorded query stats. " name="slowQueriesCD" type="[javax.management.openmbean.CompositeData;" writeable="false"/> - <operation description="Clears all the query stats" impact="ACTION" name="resetStats" returnType="void"/> - - <notification description="Notification sent out by the slow query report when a query exceeds the threshold" name="slow-query"> - <notification-type>Slow query</notification-type> - </notification> - - <notification description="Notification sent out by the slow query report when a query fails execution" name="failed-query"> - <notification-type>Failed query execution</notification-type> - </notification> - </mbean> -</mbeans-descriptors> |