1.1 --- a/distributions/debian/build.sh Wed Sep 24 22:53:30 2014 +0200
1.2 +++ b/distributions/debian/build.sh Thu Sep 25 17:50:40 2014 +0200
1.3 @@ -41,7 +41,7 @@
1.4 CONTROL_FILE="equivs-control" &&
1.5 COPYRIGHT_FILE="copyright" &&
1.6 URL="https://sql-dk.globalcode.info/" &&
1.7 -VERSION="0.9" &&
1.8 +VERSION="0.10" &&
1.9
1.10 echo "Section: database
1.11 Priority: optional
2.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java Wed Sep 24 22:53:30 2014 +0200
2.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/CLIStarter.java Thu Sep 25 17:50:40 2014 +0200
2.3 @@ -31,6 +31,8 @@
2.4 import info.globalcode.sql.dk.formatting.Formatter;
2.5 import info.globalcode.sql.dk.formatting.FormatterContext;
2.6 import info.globalcode.sql.dk.formatting.FormatterException;
2.7 +import info.globalcode.sql.dk.jmx.ConnectionManagement;
2.8 +import info.globalcode.sql.dk.jmx.ManagementUtils;
2.9 import java.io.File;
2.10 import java.io.FileNotFoundException;
2.11 import java.io.IOException;
2.12 @@ -149,7 +151,9 @@
2.13 private void processQueryNow() throws ConfigurationException, SQLException, FormatterException {
2.14 DatabaseDefinition dd = getConfiguration().getDatabase(options.getDatabaseName());
2.15 FormatterDefinition fd = configuration.getFormatter(options.getFormatterName());
2.16 - try (DatabaseConnection c = dd.connect(options.getDatabaseProperties())) {
2.17 + ConnectionManagement jmxBean = ManagementUtils.registerMBean(dd.getName());
2.18 +
2.19 + try (DatabaseConnection c = dd.connect(options.getDatabaseProperties(), jmxBean)) {
2.20 log.log(Level.FINE, "Database connected");
2.21 try (Formatter f = fd.getInstance(new FormatterContext(options.getOutputStream(), options.getFormatterProperties()))) {
2.22 c.executeQuery(options.getSQLCommand(), f);
2.23 @@ -169,7 +173,9 @@
2.24
2.25 DatabaseDefinition dd = getConfiguration().getDatabase(options.getDatabaseName());
2.26 FormatterDefinition fd = configuration.getFormatter(options.getFormatterName());
2.27 - try (DatabaseConnection c = dd.connect(options.getDatabaseProperties())) {
2.28 + ConnectionManagement jmxBean = ManagementUtils.registerMBean(dd.getName());
2.29 +
2.30 + try (DatabaseConnection c = dd.connect(options.getDatabaseProperties(), jmxBean)) {
2.31 log.log(Level.FINE, "Database connected");
2.32 try (Formatter f = fd.getInstance(new FormatterContext(options.getOutputStream(), options.getFormatterProperties()))) {
2.33 c.executeBatch(b, f);
3.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java Wed Sep 24 22:53:30 2014 +0200
3.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/DatabaseConnection.java Thu Sep 25 17:50:40 2014 +0200
3.3 @@ -17,6 +17,8 @@
3.4 */
3.5 package info.globalcode.sql.dk;
3.6
3.7 +import static info.globalcode.sql.dk.jmx.ConnectionManagement.incrementCounter;
3.8 +import static info.globalcode.sql.dk.jmx.ConnectionManagement.resetCounter;
3.9 import info.globalcode.sql.dk.batch.Batch;
3.10 import info.globalcode.sql.dk.batch.BatchException;
3.11 import info.globalcode.sql.dk.configuration.DatabaseDefinition;
3.12 @@ -24,6 +26,8 @@
3.13 import info.globalcode.sql.dk.configuration.Property;
3.14 import info.globalcode.sql.dk.formatting.ColumnsHeader;
3.15 import info.globalcode.sql.dk.formatting.Formatter;
3.16 +import info.globalcode.sql.dk.jmx.ConnectionManagement;
3.17 +import info.globalcode.sql.dk.jmx.ConnectionManagement.COUNTER;
3.18 import java.sql.Connection;
3.19 import java.sql.DriverManager;
3.20 import java.sql.PreparedStatement;
3.21 @@ -50,10 +54,23 @@
3.22 private final DatabaseDefinition databaseDefinition;
3.23 private final Connection connection;
3.24 private final Properties properties;
3.25 + /**
3.26 + * Could be null = JMX is disabled → must check, see functions in
3.27 + * {@linkplain ConnectionManagement}
3.28 + */
3.29 + private final ConnectionManagement connectionMBean;
3.30
3.31 - public DatabaseConnection(DatabaseDefinition databaseDefinition, Properties properties) throws SQLException {
3.32 + /**
3.33 + *
3.34 + * @param databaseDefinition DB url, name, password etc.
3.35 + * @param properties additional properties from CLI
3.36 + * @param connectionMBean JMX management bean | null = disabled JMX reporting
3.37 + * @throws SQLException
3.38 + */
3.39 + public DatabaseConnection(DatabaseDefinition databaseDefinition, Properties properties, ConnectionManagement connectionMBean) throws SQLException {
3.40 this.databaseDefinition = databaseDefinition;
3.41 this.properties = properties;
3.42 + this.connectionMBean = connectionMBean;
3.43
3.44 if (properties.hasProperty(JDBC_PROPERTY_PASSWORD)) {
3.45 log.log(Level.WARNING, "Passing DB password as CLI parameter is insecure!");
3.46 @@ -97,6 +114,9 @@
3.47 }
3.48
3.49 private void processCommand(SQLCommand sqlCommand, Formatter formatter) throws SQLException {
3.50 + incrementCounter(connectionMBean, COUNTER.COMMAND);
3.51 + resetCounter(connectionMBean, COUNTER.RECORD_CURRENT);
3.52 +
3.53 try (PreparedStatement ps = sqlCommand.prepareStatement(connection)) {
3.54 log.log(Level.FINE, "Statement prepared");
3.55 sqlCommand.parametrize(ps);
3.56 @@ -135,6 +155,9 @@
3.57 int columnCount = rs.getMetaData().getColumnCount();
3.58
3.59 while (rs.next()) {
3.60 + incrementCounter(connectionMBean, COUNTER.RECORD_CURRENT);
3.61 + incrementCounter(connectionMBean, COUNTER.RECORD_TOTAL);
3.62 +
3.63 formatter.writeStartRow();
3.64
3.65 for (int i = 1; i <= columnCount; i++) {
4.1 --- a/java/sql-dk/src/info/globalcode/sql/dk/configuration/DatabaseDefinition.java Wed Sep 24 22:53:30 2014 +0200
4.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/configuration/DatabaseDefinition.java Thu Sep 25 17:50:40 2014 +0200
4.3 @@ -19,7 +19,14 @@
4.4
4.5 import static info.globalcode.sql.dk.Xmlns.CONFIGURATION;
4.6 import info.globalcode.sql.dk.DatabaseConnection;
4.7 +import info.globalcode.sql.dk.jmx.ConnectionManagement;
4.8 +import java.lang.management.ManagementFactory;
4.9 import java.sql.SQLException;
4.10 +import java.util.Hashtable;
4.11 +import java.util.logging.Level;
4.12 +import java.util.logging.Logger;
4.13 +import javax.management.MBeanServer;
4.14 +import javax.management.ObjectName;
4.15 import javax.xml.bind.annotation.XmlElement;
4.16
4.17 /**
4.18 @@ -29,6 +36,7 @@
4.19 */
4.20 public class DatabaseDefinition implements NameIdentified {
4.21
4.22 + private static final Logger log = Logger.getLogger(DatabaseDefinition.class.getName());
4.23 private String name;
4.24 private String url;
4.25 private String userName;
4.26 @@ -83,8 +91,17 @@
4.27
4.28 /**
4.29 * @param properties ad-hoc properties from CLI options (for the JDBC driver)
4.30 + * @param jmxBean JMX management bean for progress reporting | null = disable JMX
4.31 + */
4.32 + public DatabaseConnection connect(Properties properties, ConnectionManagement jmxBean) throws SQLException {
4.33 + return new DatabaseConnection(this, properties, jmxBean);
4.34 + }
4.35 +
4.36 + /**
4.37 + * @see #connect(info.globalcode.sql.dk.configuration.Properties, java.lang.String)
4.38 + * With disabled JMX reporting.
4.39 */
4.40 public DatabaseConnection connect(Properties properties) throws SQLException {
4.41 - return new DatabaseConnection(this, properties);
4.42 + return new DatabaseConnection(this, properties, null);
4.43 }
4.44 }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/jmx/ConnectionManagement.java Thu Sep 25 17:50:40 2014 +0200
5.3 @@ -0,0 +1,97 @@
5.4 +/**
5.5 + * SQL-DK
5.6 + * Copyright © 2014 František Kučera (frantovo.cz)
5.7 + *
5.8 + * This program is free software: you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License as published by
5.10 + * the Free Software Foundation, either version 3 of the License, or
5.11 + * (at your option) any later version.
5.12 + *
5.13 + * This program is distributed in the hope that it will be useful,
5.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.16 + * GNU General Public License for more details.
5.17 + *
5.18 + * You should have received a copy of the GNU General Public License
5.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
5.20 + */
5.21 +package info.globalcode.sql.dk.jmx;
5.22 +
5.23 +import java.util.EnumMap;
5.24 +import java.util.Map;
5.25 +
5.26 +/**
5.27 + * JMX management bean for progress reporting.
5.28 + *
5.29 + * @author Ing. František Kučera (frantovo.cz)
5.30 + */
5.31 +public class ConnectionManagement implements ConnectionManagementMBean {
5.32 +
5.33 + private final String databaseName;
5.34 + private final Map<COUNTER, Integer> counters = new EnumMap(COUNTER.class);
5.35 +
5.36 + public ConnectionManagement(String databaseName) {
5.37 + this.databaseName = databaseName;
5.38 + for (COUNTER c : COUNTER.values()) {
5.39 + counters.put(c, 0);
5.40 + }
5.41 + }
5.42 +
5.43 + public enum COUNTER {
5.44 +
5.45 + COMMAND,
5.46 + RECORD_CURRENT,
5.47 + RECORD_TOTAL
5.48 + };
5.49 +
5.50 + public void incrementCounter(COUNTER counter) {
5.51 + synchronized (counters) {
5.52 + int old = counters.get(counter);
5.53 + counters.put(counter, old + 1);
5.54 + }
5.55 + }
5.56 +
5.57 + public void resetCounter(COUNTER counter) {
5.58 + synchronized (counters) {
5.59 + counters.put(counter, 0);
5.60 + }
5.61 + }
5.62 +
5.63 + public static void incrementCounter(ConnectionManagement mbean, COUNTER counter) {
5.64 + if (mbean != null) {
5.65 + mbean.incrementCounter(counter);
5.66 + }
5.67 + }
5.68 +
5.69 + public static void resetCounter(ConnectionManagement mbean, COUNTER counter) {
5.70 + if (mbean != null) {
5.71 + mbean.resetCounter(counter);
5.72 + }
5.73 + }
5.74 +
5.75 + @Override
5.76 + public String getDatabaseName() {
5.77 + return databaseName;
5.78 + }
5.79 +
5.80 + @Override
5.81 + public int getCommandCount() {
5.82 + synchronized (counters) {
5.83 + return counters.get(COUNTER.COMMAND);
5.84 + }
5.85 + }
5.86 +
5.87 + @Override
5.88 + public int getCurrentRecordCount() {
5.89 + synchronized (counters) {
5.90 + return counters.get(COUNTER.RECORD_CURRENT);
5.91 + }
5.92 + }
5.93 +
5.94 + @Override
5.95 + public int getTotalRecordCount() {
5.96 + synchronized (counters) {
5.97 + return counters.get(COUNTER.RECORD_TOTAL);
5.98 + }
5.99 + }
5.100 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/jmx/ConnectionManagementMBean.java Thu Sep 25 17:50:40 2014 +0200
6.3 @@ -0,0 +1,34 @@
6.4 +/**
6.5 + * SQL-DK
6.6 + * Copyright © 2014 František Kučera (frantovo.cz)
6.7 + *
6.8 + * This program is free software: you can redistribute it and/or modify
6.9 + * it under the terms of the GNU General Public License as published by
6.10 + * the Free Software Foundation, either version 3 of the License, or
6.11 + * (at your option) any later version.
6.12 + *
6.13 + * This program is distributed in the hope that it will be useful,
6.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.16 + * GNU General Public License for more details.
6.17 + *
6.18 + * You should have received a copy of the GNU General Public License
6.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
6.20 + */
6.21 +package info.globalcode.sql.dk.jmx;
6.22 +
6.23 +/**
6.24 + *
6.25 + * @author Ing. František Kučera (frantovo.cz)
6.26 + */
6.27 +public interface ConnectionManagementMBean {
6.28 +
6.29 + public String getDatabaseName();
6.30 +
6.31 + public int getCommandCount();
6.32 +
6.33 + public int getCurrentRecordCount();
6.34 +
6.35 + public int getTotalRecordCount();
6.36 +
6.37 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/java/sql-dk/src/info/globalcode/sql/dk/jmx/ManagementUtils.java Thu Sep 25 17:50:40 2014 +0200
7.3 @@ -0,0 +1,68 @@
7.4 +/**
7.5 + * SQL-DK
7.6 + * Copyright © 2014 František Kučera (frantovo.cz)
7.7 + *
7.8 + * This program is free software: you can redistribute it and/or modify
7.9 + * it under the terms of the GNU General Public License as published by
7.10 + * the Free Software Foundation, either version 3 of the License, or
7.11 + * (at your option) any later version.
7.12 + *
7.13 + * This program is distributed in the hope that it will be useful,
7.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.16 + * GNU General Public License for more details.
7.17 + *
7.18 + * You should have received a copy of the GNU General Public License
7.19 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
7.20 + */
7.21 +package info.globalcode.sql.dk.jmx;
7.22 +
7.23 +import java.lang.management.ManagementFactory;
7.24 +import java.util.Hashtable;
7.25 +import java.util.logging.Level;
7.26 +import java.util.logging.Logger;
7.27 +import javax.management.MBeanServer;
7.28 +import javax.management.ObjectName;
7.29 +
7.30 +/**
7.31 + *
7.32 + * @author Ing. František Kučera (frantovo.cz)
7.33 + */
7.34 +public class ManagementUtils {
7.35 +
7.36 + private static final Logger log = Logger.getLogger(ManagementUtils.class.getName());
7.37 + public static final String DEFAULT_CONNECTION_JMX_NAME = "main";
7.38 +
7.39 + /**
7.40 + * @see #registerMBean(java.lang.String, java.lang.String) with default JMX name
7.41 + */
7.42 + public static ConnectionManagement registerMBean(String dbName) {
7.43 + return registerMBean(dbName, DEFAULT_CONNECTION_JMX_NAME);
7.44 + }
7.45 +
7.46 + /**
7.47 + *
7.48 + * @param dbName database name
7.49 + * @param jmxName name of JMX bean
7.50 + * @return registered JMX bean | or null if registration fails (should not)
7.51 + */
7.52 + public static ConnectionManagement registerMBean(String dbName, String jmxName) {
7.53 + try {
7.54 + ConnectionManagement mbean = new ConnectionManagement(dbName);
7.55 + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
7.56 + Hashtable<String, String> objectProperties = new Hashtable<>();
7.57 + objectProperties.put("type", "Connection");
7.58 + objectProperties.put("name", jmxName);
7.59 + ObjectName objectName = new ObjectName("info.globalcode.sql.dk", objectProperties);
7.60 + mbs.registerMBean(mbean, objectName);
7.61 + log.log(Level.FINE, "JMX MBean was registered as: {0}", objectName);
7.62 + return mbean;
7.63 + } catch (Exception e) {
7.64 + log.log(Level.WARNING, "Unable to register JMX MBean", e);
7.65 + return null;
7.66 + }
7.67 + }
7.68 +
7.69 + private ManagementUtils() {
7.70 + }
7.71 +}