Internal help: Warn for potential db corruption issues
This commit is contained in:
committed by
jvoisin
parent
768968d075
commit
55f9a41673
@@ -20,6 +20,7 @@
|
||||
package org.airsonic.player.controller;
|
||||
|
||||
import org.airsonic.player.dao.DaoHelper;
|
||||
import org.airsonic.player.dao.MediaFileDao;
|
||||
import org.airsonic.player.dao.MusicFolderDao;
|
||||
import org.airsonic.player.domain.MediaLibraryStatistics;
|
||||
import org.airsonic.player.domain.MusicFolder;
|
||||
@@ -162,6 +163,8 @@ public class InternalHelpController {
|
||||
@Autowired
|
||||
private MusicFolderDao musicFolderDao;
|
||||
@Autowired
|
||||
private MediaFileDao mediaFileDao;
|
||||
@Autowired
|
||||
private TranscodingService transcodingService;
|
||||
|
||||
@GetMapping
|
||||
@@ -311,6 +314,12 @@ public class InternalHelpController {
|
||||
map.put("dbMediaFileDistinctArtistCount", daoHelper.getJdbcTemplate().queryForObject(String.format("SELECT count(DISTINCT artist) FROM MEDIA_FILE WHERE present"), Long.class));
|
||||
map.put("dbMediaFileDistinctAlbumArtistCount", daoHelper.getJdbcTemplate().queryForObject(String.format("SELECT count(DISTINCT album_artist) FROM MEDIA_FILE WHERE present"), Long.class));
|
||||
|
||||
map.put("dbMediaFilesInNonPresentMusicFoldersCount", mediaFileDao.getFilesInNonPresentMusicFoldersCount(Arrays.asList(settingsService.getPodcastFolder())));
|
||||
map.put("dbMediaFilesInNonPresentMusicFoldersSample", mediaFileDao.getFilesInNonPresentMusicFolders(10, Arrays.asList(settingsService.getPodcastFolder())));
|
||||
|
||||
map.put("dbMediaFilesWithMusicFolderMismatchCount", mediaFileDao.getFilesWithMusicFolderMismatchCount());
|
||||
map.put("dbMediaFilesWithMusicFolderMismatchSample", mediaFileDao.getFilesWithMusicFolderMismatch(10));
|
||||
|
||||
map.put("dbTableCount", dbTableCount);
|
||||
}
|
||||
|
||||
|
||||
@@ -597,6 +597,67 @@ public class MediaFileDao extends AbstractDao {
|
||||
return namedQuery(query, rowMapper, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of media file objects that don't belong to an existing music folder
|
||||
* @param count maximum number of media file objects to return
|
||||
* @param excludeFolders music folder paths excluded from the results
|
||||
* @return a list of media files, sorted by id
|
||||
*/
|
||||
public List<MediaFile> getFilesInNonPresentMusicFolders(final int count, List<String> excludeFolders) {
|
||||
Map<String, Object> args = new HashMap<>();
|
||||
args.put("excludeFolders", excludeFolders);
|
||||
args.put("count", count);
|
||||
return namedQuery(
|
||||
"SELECT " + prefix(QUERY_COLUMNS, "media_file") + " FROM media_file " +
|
||||
"LEFT OUTER JOIN music_folder ON music_folder.path = media_file.folder " +
|
||||
"WHERE music_folder.id IS NULL " +
|
||||
"AND media_file.folder NOT IN (:excludeFolders) " +
|
||||
"ORDER BY media_file.id LIMIT :count",
|
||||
rowMapper, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of media files that don't belong to an existing music folder
|
||||
* @param excludeFolders music folder paths excluded from the results
|
||||
* @return a number of media file rows in the database
|
||||
*/
|
||||
public int getFilesInNonPresentMusicFoldersCount(List<String> excludeFolders) {
|
||||
Map<String, Object> args = new HashMap<>();
|
||||
args.put("excludeFolders", excludeFolders);
|
||||
return namedQueryForInt(
|
||||
"SELECT count(media_file.id) FROM media_file " +
|
||||
"LEFT OUTER JOIN music_folder ON music_folder.path = media_file.folder " +
|
||||
"WHERE music_folder.id IS NULL " +
|
||||
"AND media_file.folder NOT IN (:excludeFolders) ",
|
||||
0, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of media file objects whose path don't math their music folder
|
||||
* @param count maximum number of media file objects to return
|
||||
* @return a list of media files, sorted by id
|
||||
*/
|
||||
public List<MediaFile> getFilesWithMusicFolderMismatch(final int count) {
|
||||
return query(
|
||||
"SELECT " + prefix(QUERY_COLUMNS, "media_file") + " FROM media_file " +
|
||||
"WHERE media_file.path != media_file.folder " +
|
||||
"AND media_file.path NOT LIKE concat(media_file.folder, '/%') " +
|
||||
"ORDER BY media_file.id LIMIT ?",
|
||||
rowMapper, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of media files whose path don't math their music folder
|
||||
* @return a number of media file rows in the database
|
||||
*/
|
||||
public int getFilesWithMusicFolderMismatchCount() {
|
||||
return queryForInt(
|
||||
"SELECT count(media_file.id) FROM media_file " +
|
||||
"WHERE media_file.path != media_file.folder " +
|
||||
"AND media_file.path NOT LIKE concat(media_file.folder, '/%')",
|
||||
0);
|
||||
}
|
||||
|
||||
public int getAlbumCount(final List<MusicFolder> musicFolders) {
|
||||
if (musicFolders.isEmpty()) {
|
||||
return 0;
|
||||
|
||||
@@ -266,6 +266,7 @@ internalhelp.title=About {0} Internals
|
||||
internalhelp.details=Internal details
|
||||
internalhelp.statistics=Statistics
|
||||
internalhelp.database=Database
|
||||
internalhalp.databaseconsistency=Database Consistency
|
||||
internalhelp.index=Search Index
|
||||
internalhelp.filesystem=Filesystem
|
||||
internalhelp.transcoding=Transcoding
|
||||
|
||||
@@ -151,6 +151,65 @@
|
||||
|
||||
<p></p>
|
||||
|
||||
<h2>
|
||||
<img src="<spring:theme code='logImage'/>" alt="">
|
||||
<span style="vertical-align: middle"><fmt:message key="internalhalp.databaseconsistency"/></span>
|
||||
</h2>
|
||||
|
||||
<table width="75%" class="ruleTable indent">
|
||||
<tr>
|
||||
<td colspan="3" class="ruleTableCell">
|
||||
<c:choose>
|
||||
<c:when test="${model.dbMediaFilesInNonPresentMusicFoldersCount == 0}">
|
||||
<img src="<spring:theme code='checkImage'/>" alt="OK">
|
||||
All media files in the database have a valid music folder.
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<img src="<spring:theme code='alertImage'/>" alt="Warning">
|
||||
The media file database contains files whose music folder is no longer present. Examples are below.
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td class="ruleTableHeader">dbMediaFilesInNonPresentMusicFoldersCount</td><td class="ruleTableCell" colspan="2">${model.dbMediaFilesInNonPresentMusicFoldersCount}</td></tr>
|
||||
<c:if test="${model.dbMediaFilesInNonPresentMusicFoldersCount > 0}">
|
||||
<tr><td class="ruleTableHeader">ID</td><td class="ruleTableHeader">PATH</td><td class="ruleTableHeader">FOLDER</td></tr>
|
||||
<c:forEach var="invalidFolderSample" items="${model.dbMediaFilesInNonPresentMusicFoldersSample}">
|
||||
<tr><td class="ruleTableHeader">${invalidFolderSample.id}</td><td class="ruleTableCell">${invalidFolderSample.path}</td><td class="ruleTableCell">${invalidFolderSample.folder}</td></tr>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</table>
|
||||
|
||||
<p></p>
|
||||
|
||||
<table width="75%" class="ruleTable indent">
|
||||
<tr>
|
||||
<td colspan="3" class="ruleTableCell">
|
||||
<c:choose>
|
||||
<c:when test="${model.dbMediaFilesWithMusicFolderMismatchCount == 0}">
|
||||
<img src="<spring:theme code='checkImage'/>" alt="OK">
|
||||
All media files in the database match their music folder.
|
||||
</c:when>
|
||||
<c:otherwise>
|
||||
<img src="<spring:theme code='alertImage'/>" alt="Warning">
|
||||
The media file database contains files whose path does not match their music folder path. Examples are below.
|
||||
</c:otherwise>
|
||||
</c:choose>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr><td class="ruleTableHeader">dbMediaFilesWithMusicFolderMismatchCount</td><td class="ruleTableCell" colspan="2">${model.dbMediaFilesWithMusicFolderMismatchCount}</td></tr>
|
||||
<c:if test="${model.dbMediaFilesWithMusicFolderMismatchCount > 0}">
|
||||
<tr><td class="ruleTableHeader">ID</td><td class="ruleTableHeader">PATH</td><td class="ruleTableHeader">FOLDER</td></tr>
|
||||
<c:forEach var="mismatchSample" items="${model.dbMediaFilesWithMusicFolderMismatchSample}">
|
||||
<tr><td class="ruleTableHeader">${mismatchSample.id}</td><td class="ruleTableCell">${mismatchSample.path}</td><td class="ruleTableCell">${mismatchSample.folder}</td></tr>
|
||||
</c:forEach>
|
||||
</c:if>
|
||||
</table>
|
||||
|
||||
<p></p>
|
||||
|
||||
<h2>
|
||||
<img src="<spring:theme code='logImage'/>" alt="">
|
||||
<span style="vertical-align: middle"><fmt:message key="internalhelp.filesystem"/></span>
|
||||
|
||||
Reference in New Issue
Block a user