Force database checkpoints on 'Clean-up' and 'Scan' actions

This will only affect the (embedded/legacy) HSQLDB driver. Even though
cff97ea9 should prevent the db log from getting uncontrollably large,
the 'Clean-up database' and 'Scan' actions will additionally force a
checkpoint to ensure this happens on big operations.
master
François-Xavier Thomas 6 years ago
parent 3fb697ddce
commit c0f3606091
  1. 1
      airsonic-main/src/main/java/org/airsonic/player/controller/MusicFolderSettingsController.java
  2. 2
      airsonic-main/src/main/java/org/airsonic/player/dao/AbstractDao.java
  3. 10
      airsonic-main/src/main/java/org/airsonic/player/dao/DaoHelper.java
  4. 39
      airsonic-main/src/main/java/org/airsonic/player/dao/GenericDaoHelper.java
  5. 1
      airsonic-main/src/main/java/org/airsonic/player/service/MediaScannerService.java

@ -96,6 +96,7 @@ public class MusicFolderSettingsController {
artistDao.expunge(); artistDao.expunge();
albumDao.expunge(); albumDao.expunge();
mediaFileDao.expunge(); mediaFileDao.expunge();
mediaFileDao.checkpoint();
} }
private List<MusicFolderSettingsCommand.MusicFolderInfo> wrap(List<MusicFolder> musicFolders) { private List<MusicFolderSettingsCommand.MusicFolderInfo> wrap(List<MusicFolder> musicFolders) {

@ -189,4 +189,6 @@ public class AbstractDao {
this.daoHelper = daoHelper; this.daoHelper = daoHelper;
} }
public boolean checkpoint() { return daoHelper.checkpoint(); }
} }

@ -46,4 +46,14 @@ public interface DaoHelper {
NamedParameterJdbcTemplate getNamedParameterJdbcTemplate(); NamedParameterJdbcTemplate getNamedParameterJdbcTemplate();
DataSource getDataSource(); DataSource getDataSource();
/**
* Tries to perform a checkpoint against the database, if supported
*
* Database checkpoints will make sure that the database is written on the disk
* and optimize on-disk storage.
*
* @return true if the checkpoint succeeded
*/
public boolean checkpoint();
} }

@ -1,12 +1,20 @@
package org.airsonic.player.dao; package org.airsonic.player.dao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
public class GenericDaoHelper implements DaoHelper { public class GenericDaoHelper implements DaoHelper {
private static final Logger LOG = LoggerFactory.getLogger(GenericDaoHelper.class);
final JdbcTemplate jdbcTemplate; final JdbcTemplate jdbcTemplate;
final NamedParameterJdbcTemplate namedParameterJdbcTemplate; final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@ -35,4 +43,35 @@ public class GenericDaoHelper implements DaoHelper {
public DataSource getDataSource() { public DataSource getDataSource() {
return dataSource; 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;
}
} }

@ -156,6 +156,7 @@ public class MediaScannerService {
public void run() { public void run() {
doScanLibrary(); doScanLibrary();
playlistService.importPlaylists(); playlistService.importPlaylists();
mediaFileDao.checkpoint();
} }
}; };

Loading…
Cancel
Save