Add expunge to IndexManager

When DB expunge is invoked from the management screen,
also indexManager performs expunge.

Signed-off-by: Andrew DeMaria <lostonamountain@gmail.com>
This commit is contained in:
tesshucom
2019-10-05 19:19:16 -06:00
committed by Andrew DeMaria
parent c6ae5a1df7
commit 645fb88c7d
7 changed files with 304 additions and 3 deletions
@@ -26,6 +26,7 @@ import org.airsonic.player.dao.MediaFileDao;
import org.airsonic.player.domain.MusicFolder;
import org.airsonic.player.service.MediaScannerService;
import org.airsonic.player.service.SettingsService;
import org.airsonic.player.service.search.IndexManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -63,6 +64,8 @@ public class MusicFolderSettingsController {
private AlbumDao albumDao;
@Autowired
private MediaFileDao mediaFileDao;
@Autowired
private IndexManager indexManager;
@GetMapping
protected String displayForm() throws Exception {
@@ -98,6 +101,14 @@ public class MusicFolderSettingsController {
private void expunge() {
// to be before dao#expunge
LOG.debug("Cleaning search index...");
indexManager.startIndexing();
indexManager.expunge();
indexManager.stopIndexing();
LOG.debug("Search index cleanup complete.");
LOG.debug("Cleaning database...");
LOG.debug("Deleting non-present artists...");
artistDao.expunge();
@@ -343,6 +343,10 @@ public class AlbumDao extends AbstractDao {
}
}
public List<Integer> getExpungeCandidates() {
return queryForInts("select id from album where not present");
}
public void expunge() {
int minId = queryForInt("select min(id) from album where not present", 0);
int maxId = queryForInt("select max(id) from album where not present", 0);
@@ -169,6 +169,10 @@ public class ArtistDao extends AbstractDao {
}
}
public List<Integer> getExpungeCandidates() {
return queryForInts("select id from artist where not present");
}
public void expunge() {
int minId = queryForInt("select min(id) from artist where not present", 0);
int maxId = queryForInt("select max(id) from artist where not present", 0);
@@ -661,6 +661,22 @@ public class MediaFileDao extends AbstractDao {
}
}
public List<Integer> getArtistExpungeCandidates() {
return queryForInts("select id from media_file where media_file.type = ? and not present",
MediaFile.MediaType.DIRECTORY.name());
}
public List<Integer> getAlbumExpungeCandidates() {
return queryForInts("select id from media_file where media_file.type = ? and not present",
MediaFile.MediaType.ALBUM.name());
}
public List<Integer> getSongExpungeCandidates() {
return queryForInts("select id from media_file where media_file.type in (?,?,?,?) and not present",
MediaFile.MediaType.MUSIC.name(), MediaFile.MediaType.PODCAST.name(),
MediaFile.MediaType.AUDIOBOOK.name(), MediaFile.MediaType.VIDEO.name());
}
public void expunge() {
int minId = queryForInt("select min(id) from media_file where not present", 0);
int maxId = queryForInt("select max(id) from media_file where not present", 0);
@@ -127,16 +127,20 @@ public class DocumentFactory {
doc.add(new SortedDocValuesField(fieldName, new BytesRef(value)));
};
public final Term createPrimarykey(Integer id) {
return new Term(FieldNames.ID, Integer.toString(id));
};
public final Term createPrimarykey(Album album) {
return new Term(FieldNames.ID, Integer.toString(album.getId()));
return createPrimarykey(album.getId());
};
public final Term createPrimarykey(Artist artist) {
return new Term(FieldNames.ID, Integer.toString(artist.getId()));
return createPrimarykey(artist.getId());
};
public final Term createPrimarykey(MediaFile mediaFile) {
return new Term(FieldNames.ID, Integer.toString(mediaFile.getId()));
return createPrimarykey(mediaFile.getId());
};
/**
@@ -20,6 +20,9 @@
package org.airsonic.player.service.search;
import org.airsonic.player.dao.AlbumDao;
import org.airsonic.player.dao.ArtistDao;
import org.airsonic.player.dao.MediaFileDao;
import org.airsonic.player.domain.Album;
import org.airsonic.player.domain.Artist;
import org.airsonic.player.domain.MediaFile;
@@ -99,6 +102,15 @@ public class IndexManager {
@Autowired
private DocumentFactory documentFactory;
@Autowired
private MediaFileDao mediaFileDao;
@Autowired
private ArtistDao artistDao;
@Autowired
private AlbumDao albumDao;
private Map<IndexType, SearcherManager> searchers = new HashMap<>();
private Map<IndexType, IndexWriter> writers = new HashMap<>();
@@ -163,6 +175,55 @@ public class IndexManager {
return new IndexWriter(FSDirectory.open(indexDirectory.toPath()), config);
}
public void expunge() {
Term[] primarykeys = mediaFileDao.getArtistExpungeCandidates().stream()
.map(m -> documentFactory.createPrimarykey(m))
.toArray(i -> new Term[i]);
try {
writers.get(IndexType.ARTIST).deleteDocuments(primarykeys);
} catch (IOException e) {
LOG.error("Failed to delete artist doc.", e);
}
primarykeys = mediaFileDao.getAlbumExpungeCandidates().stream()
.map(m -> documentFactory.createPrimarykey(m))
.toArray(i -> new Term[i]);
try {
writers.get(IndexType.ALBUM).deleteDocuments(primarykeys);
} catch (IOException e) {
LOG.error("Failed to delete album doc.", e);
}
primarykeys = mediaFileDao.getSongExpungeCandidates().stream()
.map(m -> documentFactory.createPrimarykey(m))
.toArray(i -> new Term[i]);
try {
writers.get(IndexType.SONG).deleteDocuments(primarykeys);
} catch (IOException e) {
LOG.error("Failed to delete song doc.", e);
}
primarykeys = artistDao.getExpungeCandidates().stream()
.map(m -> documentFactory.createPrimarykey(m))
.toArray(i -> new Term[i]);
try {
writers.get(IndexType.ARTIST_ID3).deleteDocuments(primarykeys);
} catch (IOException e) {
LOG.error("Failed to delete artistId3 doc.", e);
}
primarykeys = albumDao.getExpungeCandidates().stream()
.map(m -> documentFactory.createPrimarykey(m))
.toArray(i -> new Term[i]);
try {
writers.get(IndexType.ALBUM_ID3).deleteDocuments(primarykeys);
} catch (IOException e) {
LOG.error("Failed to delete albumId3 doc.", e);
}
}
/**
* Close Writer of all indexes and update SearcherManager.
* Called at the end of the Scan flow.