From 76e8abd219c36d128b2c78245fb2d484d94816b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Thomas?= Date: Sat, 9 Mar 2019 13:24:58 +0100 Subject: [PATCH] Move HSQLDB checkpoint/shutdown to a bean specific to the legacy profile --- .../java/org/airsonic/player/Application.java | 6 -- .../org/airsonic/player/dao/DaoHelper.java | 4 +- .../airsonic/player/dao/GenericDaoHelper.java | 35 ----------- .../player/dao/LegacyHsqlDaoHelper.java | 60 +++++++++++++++++++ .../airsonic/player/spring/TerminateBean.java | 55 ----------------- .../applicationContext-db-legacy.xml | 10 +++- .../main/resources/applicationContext-db.xml | 14 ++--- 7 files changed, 77 insertions(+), 107 deletions(-) create mode 100644 airsonic-main/src/main/java/org/airsonic/player/dao/LegacyHsqlDaoHelper.java delete mode 100644 airsonic-main/src/main/java/org/airsonic/player/spring/TerminateBean.java diff --git a/airsonic-main/src/main/java/org/airsonic/player/Application.java b/airsonic-main/src/main/java/org/airsonic/player/Application.java index 1b69c429..25857afe 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/Application.java +++ b/airsonic-main/src/main/java/org/airsonic/player/Application.java @@ -2,7 +2,6 @@ package org.airsonic.player; import net.sf.ehcache.constructs.web.ShutdownListener; import org.airsonic.player.filter.*; -import org.airsonic.player.spring.TerminateBean; import org.directwebremoting.servlet.DwrServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -57,11 +56,6 @@ public class Application extends SpringBootServletInitializer implements Embedde return servlet; } - @Bean - public TerminateBean terminateBean() { - return new TerminateBean(); - } - @Bean public ServletRegistrationBean cxfServletBean() { return new ServletRegistrationBean(new org.apache.cxf.transport.servlet.CXFServlet(), "/ws/*"); diff --git a/airsonic-main/src/main/java/org/airsonic/player/dao/DaoHelper.java b/airsonic-main/src/main/java/org/airsonic/player/dao/DaoHelper.java index 5a5c2a84..5590b5cf 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/dao/DaoHelper.java +++ b/airsonic-main/src/main/java/org/airsonic/player/dao/DaoHelper.java @@ -53,7 +53,7 @@ public interface DaoHelper { * Database checkpoints will make sure that the database is written on the disk * and optimize on-disk storage. * - * @return true if the checkpoint succeeded + * @return true if the checkpoint succeeded, false otherwise */ - public boolean checkpoint(); + public default boolean checkpoint() { return false; } } diff --git a/airsonic-main/src/main/java/org/airsonic/player/dao/GenericDaoHelper.java b/airsonic-main/src/main/java/org/airsonic/player/dao/GenericDaoHelper.java index 513ee03f..32528607 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/dao/GenericDaoHelper.java +++ b/airsonic-main/src/main/java/org/airsonic/player/dao/GenericDaoHelper.java @@ -4,13 +4,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceUtils; import javax.sql.DataSource; -import java.sql.Connection; -import java.sql.DatabaseMetaData; - public class GenericDaoHelper implements DaoHelper { private static final Logger LOG = LoggerFactory.getLogger(GenericDaoHelper.class); @@ -43,35 +39,4 @@ public class GenericDaoHelper implements DaoHelper { public DataSource getDataSource() { return dataSource; } - - @Override - public boolean checkpoint() { - - try { - Connection conn = DataSourceUtils.getConnection(getJdbcTemplate().getDataSource()); - DatabaseMetaData meta = conn.getMetaData(); - String productName = meta.getDatabaseProductName(); - int productVersion = meta.getDatabaseMajorVersion(); - - // HSQLDB (at least version 1) does not handle automatic checkpoints very well by default. - // This makes sure the temporary log is actually written to more persistent storage. - if (productName.equals("HSQL Database Engine") && (productVersion == 1 || productVersion == 2)) { - LOG.info("Performing database checkpoint"); - getJdbcTemplate().execute("CHECKPOINT DEFRAG"); - return true; - } else { - LOG.debug("Database checkpoint not implemented for '" + productName + "'"); - return false; - } - } - - // Since this method is a best-effort operation, we don't want to show - // a message if the checkpoint failed ; just assume the operation is - // unsupported. - catch(java.sql.SQLException e) { - LOG.debug("An exception occurred during database checkpoint: " + e.toString()); - } - - return false; - } } diff --git a/airsonic-main/src/main/java/org/airsonic/player/dao/LegacyHsqlDaoHelper.java b/airsonic-main/src/main/java/org/airsonic/player/dao/LegacyHsqlDaoHelper.java new file mode 100644 index 00000000..b199a75c --- /dev/null +++ b/airsonic-main/src/main/java/org/airsonic/player/dao/LegacyHsqlDaoHelper.java @@ -0,0 +1,60 @@ +package org.airsonic.player.dao; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceUtils; + +import javax.annotation.PreDestroy; +import javax.sql.DataSource; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * Special Dao Helper with additional features for managing the legacy embedded HSQL database. + */ +public class LegacyHsqlDaoHelper extends GenericDaoHelper { + + private static final Logger LOG = LoggerFactory.getLogger(LegacyHsqlDaoHelper.class); + + public LegacyHsqlDaoHelper(DataSource dataSource) { + super(dataSource); + } + + @Override + public boolean checkpoint() { + // HSQLDB (at least version 1) does not handle automatic checkpoints very well by default. + // This makes sure the temporary log is actually written to more persistent storage. + LOG.info("Database checkpoint in progress..."); + getJdbcTemplate().execute("CHECKPOINT DEFRAG"); + LOG.info("Database checkpoint complete."); + return true; + } + + @PreDestroy + public void onDestroy() { + Connection conn = null; + try { + // Properly shutdown the embedded HSQLDB database. + LOG.info("Database shutdown in progress..."); + JdbcTemplate jdbcTemplate = getJdbcTemplate(); + conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource()); + conn.setAutoCommit(true); + jdbcTemplate.execute("SHUTDOWN"); + LOG.info("Database shutdown complete."); + + } catch (SQLException e) { + LOG.error("Database shutdown failed: " + e); + e.printStackTrace(); + + } finally { + try { + if(conn != null) + conn.close(); + } catch(Exception ex) { + ex.printStackTrace(); + } + } + } +} diff --git a/airsonic-main/src/main/java/org/airsonic/player/spring/TerminateBean.java b/airsonic-main/src/main/java/org/airsonic/player/spring/TerminateBean.java deleted file mode 100644 index 9c6e83f4..00000000 --- a/airsonic-main/src/main/java/org/airsonic/player/spring/TerminateBean.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.airsonic.player.spring; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.datasource.DataSourceUtils; - -import javax.annotation.PreDestroy; -import javax.sql.DataSource; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.SQLException; - -public class TerminateBean { - - private static final Logger LOG = LoggerFactory.getLogger(TerminateBean.class); - - @Autowired - private ApplicationContext context; - - @PreDestroy - public void onDestroy() { - Connection conn = null; - try { - // Connect to the database and retrieve the db name and version - JdbcTemplate jdbcTemplate = new JdbcTemplate(this.context.getBean(DataSource.class)); - conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource()); - DatabaseMetaData meta = conn.getMetaData(); - String productName = meta.getDatabaseProductName(); - int productVersion = meta.getDatabaseMajorVersion(); - - // Properly shutdown HSQLDB databases - if (productName.equals("HSQL Database Engine") && (productVersion == 1 || productVersion == 2)) { - LOG.info("Database shutdown in progress..."); - conn.setAutoCommit(true); - jdbcTemplate.execute("SHUTDOWN"); - LOG.info("Database shutdown complete."); - } - - } catch (SQLException e) { - e.printStackTrace(); - - } finally { - try { - if(conn != null) - conn.close(); - } catch(Exception ex) { - ex.printStackTrace(); - } - } - } -} diff --git a/airsonic-main/src/main/resources/applicationContext-db-legacy.xml b/airsonic-main/src/main/resources/applicationContext-db-legacy.xml index f866f385..b933f284 100644 --- a/airsonic-main/src/main/resources/applicationContext-db-legacy.xml +++ b/airsonic-main/src/main/resources/applicationContext-db-legacy.xml @@ -6,11 +6,17 @@ - - \ No newline at end of file + + + + + + + + diff --git a/airsonic-main/src/main/resources/applicationContext-db.xml b/airsonic-main/src/main/resources/applicationContext-db.xml index c3e13b7c..de2db1ae 100644 --- a/airsonic-main/src/main/resources/applicationContext-db.xml +++ b/airsonic-main/src/main/resources/applicationContext-db.xml @@ -3,12 +3,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> - - - - - - @@ -17,6 +11,12 @@ + + + + + + @@ -38,4 +38,4 @@ - \ No newline at end of file +